uses
  uCPUMem, uDisk, xspChart, xsGraphics,//screen,
  menus, IniFiles, sysutils;

const
  TextLeft=6;         //所有文字的X坐标
  TextTop=12;         //文字起始高度
  TextWidth=115;      //文字宽度
  TextBottom=15;      //最下面留空的距离
  
  
  RefreshDrivesInterval=10; //磁盘信息刷新间隔时间(默认每10秒刷新一次)

  

var
  tmr:TTimer;
  ShowCore, ShowMemory, ShowNetwork, ShowDrives, ShowChart:boolean;
  CurrentTop:integer;
  //
  TitleSize,        //标题文字大小
  TitleHeight,      //标题高度
  TitleSep,         //标题之前的间隔
  TitleColor:integer; //标题颜色
  
  ItemSize,         //子项文字大小
  ItemHeight,       //子项高度
  ItemColor:integer;//子项颜色
  TextFont:string;  //文字字体名称
  TextBlur,            //文字是否羽化
  TextShadow :boolean; //文字阴影
  //--- Cores ---
  Cores,CoreValues:TStrings;
  ShowAllCore:boolean;  //是否显示所有核心的使用率(默认显示)
  //--- Memory ---
  lblMemory,lblMemoryValue,
  lblUsed,lblUsedValue,
  lblFree,lblFreeValue,
  lblTotal,lblTotalValue :TxspLabel;
  //--- Drives ---
  Drives,DriveValues:TStrings;
  DriveName:string;
  iRefreshDrivesIntervalTimes:integer;
  //--- Network ---
  lblNetwork,lblNetworkValue,
  lblIP,lblIPValue,
  lblUp,lblUpValue,
  lblDown,lblDownValue,
  lblUpDownSize,lblUpDownSizeValue :TxspLabel;
  MaxSpeed,PrevSpeed:Int64;
  isAutoMaxSpeed:boolean;
  //--- Chart ---
  chart, chart2:TxspChart; 
  ChartInfoType:integer; //曲线图显示的内容(默认为0，表示显示CPU使用率)

  ChartColor,    //曲线图颜色
  ChartColorTo,  //曲线图渐进颜色
  Chart2Color,   //第二个曲线图颜色
  Chart2ColorTo, //第二个曲线图渐进颜色
  ChartGridColor,//曲线背景颜色
  ChartHeight:integer;
  
  SkinName:string;
  

//添加一行Label
procedure NewItems(var lbl:TxspLabel; aCaption:string; var lblValue:TxspLabel; isTitle:boolean; bVisible:boolean);
begin
  if lbl=nil then
  	lbl:=TxspLabel.Create(Widget);
  if lblValue=nil then
    lblValue:=TxspLabel.Create(Widget);
  lbl.visible:=bVisible;
  lblValue.visible:=bVisible;
  if not bVisible then exit;
  
  with lbl do
  begin
    parent:=Widget;
    caption:=aCaption;
    left:=TextLeft;
    width:=TextWidth;
    if TextFont<>'' then
      FontStyle.Font.Name:=TextFont
    else
      FontStyle.Font.Name:='Arial';
    FontStyle.Blur:=TextBlur;
    FontStyle.ShadowStyle.Enabled:=TextShadow;
    if isTitle then
    begin
      if CurrentTop=0 then top:=TextTop
        else top:=CurrentTop+TitleSep;
      height:=TitleHeight
      FontStyle.Font.Color:=TitleColor;
	    FontStyle.Font.Size:=TitleSize;
	  end
    else
    begin
      top:=CurrentTop;
      height:=ItemHeight;
	    FontStyle.Font.Color:=ItemColor;
	    FontStyle.Font.Size:=ItemSize;
	  end;
    CurrentTop:=top+height;
  end;
  with lblValue do
  begin
    parent:=Widget;
    caption:='';
    top:=lbl.top;      left:=lbl.left;
    width:=lbl.width;  height:=lbl.height;
    if TextFont<>'' then
      FontStyle.Font.Name:=TextFont
    else
      FontStyle.Font.Name:='Arial';

    FontStyle.Font.Color:=lbl.FontStyle.Font.Color;
    FontStyle.Font.Size:=lbl.FontStyle.Font.Size;
    FontStyle.Align:=xaTopRight;
    FontStyle.Blur:=TextBlur;
    FontStyle.ShadowStyle.Enabled:=TextShadow;
  end;
  
  SetAllowMoveWidget(lblValue,true);
end;

function AddSkinMenuItem(aCaption:string; aTag:Integer; aProcedure:string):TMenuItem;
begin
	result:=nil;
	result:=TMenuItem.Create(Widget);
	with result do
	begin
	  OnClick:=aProcedure;
	  tag:=aTag;
	  caption:=aCaption;
	  AutoCheck:=true;
	  RadioItem:=true;
  	nSkin.add(result);
	end;
end;

//CPU
procedure InitCores;
var
  i:integer;
  lbl,lblValue:TxspLabel;
begin
  if (cpuCount<=0) then
  begin
    ShowCore:=false;
    nShowCore.Checked:=false;
    exit;
  end;
  if (cpuCount=1) then ShowAllCore:=false;
  if Cores=nil then
  begin
    if not ShowCore then exit;
  	Cores:=TStringList.create;
  end;
  if CoreValues=nil then
  	CoreValues:=TStringList.create;
  for i:=0 to cpuCount do
  begin
    if Cores.count>i then lbl:=TxspLabel(Cores.Objects[i])
      else lbl:=nil;
    if CoreValues.count>i then lblValue:=TxspLabel(CoreValues.Objects[i])
      else lblValue:=nil;

    if i=0 then
    	NewItems(lbl,'Processor',lblValue,true,ShowCore)
    else
    	NewItems(lbl,'Core '+IntToStr(i),lblValue,false,ShowAllCore);
    if Cores.count<=i then
      Cores.AddObject(IntToStr(i),lbl);
    if CoreValues.count<=i then
      CoreValues.AddObject(IntToStr(i),lblValue);
  end;
end;

//内存
procedure InitMemory;
begin
  if not ShowMemory and (lblMemory=nil) then exit;

  NewItems(lblMemory,'Memory',lblMemoryValue,true,ShowMemory);
  NewItems(lblUsed,'Used',lblUsedValue,false,ShowMemory);
  NewItems(lblFree,'Free',lblFreeValue,false,ShowMemory);
  NewItems(lblTotal,'Total',lblTotalValue,false,ShowMemory);
  
  lblTotalValue.caption:=IntToStr(TotalMem)+'MB';
end;

//磁盘信息
procedure InitDrives;
var
  i:integer;
  lbl,lblValue:TxspLabel;
begin
  DriveName:=GetValidDrives;
  if length(DriveName)<=0 then exit;
  if DriveName[0]='A' then DriveName:=copy(DriveName,2,length(DriveName)-1);
  if Drives=nil then
  begin
    if not ShowDrives then exit;
    Drives:=TStringList.create;
  end;
  if DriveValues=nil then DriveValues:=TStringList.create;
  if not ShowDrives then
  begin
    for i:=0 to Drives.count-1 do
    begin
      TxspLabel(Drives.Objects[i]).visible:=ShowDrives;
      TxspLabel(DriveValues.Objects[i]).visible:=ShowDrives;
    end;
    exit;
  end;
  for i:=0 to length(DriveName) do
  begin
    if Drives.count>i then lbl:=TxspLabel(Drives.Objects[i])
      else lbl:=nil;
    if DriveValues.count>i then lblValue:=TxspLabel(DriveValues.Objects[i])
      else lblValue:=nil;
    if i=0 then
    	NewItems(lbl,'Drives',lblValue,true,ShowDrives)
    else
    	NewItems(lbl,DriveName[i],lblValue,false,ShowDrives);
    //lbl.visible:=ShowDrives;
    //lblValue.visible:=ShowDrives;
    if Drives.count<=i then
	    Drives.AddObject(IntToStr(i),lbl);
    if DriveValues.count<=i then
      DriveValues.AddObject(IntToStr(i),lblValue);
  end;
end;

//网络流量
procedure InitNetwork;
begin
  if not ShowNetwork and (lblNetwork=nil) then exit;

  NewItems(lblNetwork,'Network',lblNetworkValue,true,ShowNetwork);
  NewItems(lblIP,'IP',lblIPValue,false,ShowNetwork);
  NewItems(lblUp,'Upload',lblUpValue,false,ShowNetwork);
  NewItems(lblDown,'Download',lblDownValue,false,ShowNetwork);
  NewItems(lblUpDownSize,'Size',lblUpDownSizeValue,false,ShowNetwork);
end;

//图表
procedure InitChart;
begin
  if chart2=nil then
  begin
    if not ShowChart then exit;
	  chart2:=TxspChart.Create(Widget); 
	end;
	if not ShowChart then
	begin
	  chart.visible:=ShowChart;
	  chart2.visible:=ShowChart;
	  exit;
	end;
  with chart2 do
  begin
    parent:=Widget;
    visible:=ShowChart;
    top:=CurrentTop+TitleSep;
    left:=TextLeft;
    width:=TextWidth;
    height:=ChartHeight;
    FillStyle:=xsfGradientCurve; //xsfColorCurve,xsfGradientFill

    penStyle.Color:=Chart2ColorTo;
    penStyle.Opacity:=255;
    bgPatternColor:=ChartGridColor;
    bgOpacity:=10;
    bgStyle:=xhsDottedGrid; //xhsSmallGrid;
    BorderStyle.Enabled:=false;
    GradientStyle.ColorBegin:=Chart2Color;
    GradientStyle.ColorEnd:=Chart2ColorTo;
    GradientStyle.Opacity:=255;
    GradientStyle.OpacityEnd:=255;
    CurrentTop:=CurrentTop+height;
  end;
  if chart=nil then
    chart:=TxspChart.Create(Widget); 
  with chart do
  begin
    parent:=Widget;
    visible:=ShowChart;
    top:=chart2.top;
    left:=chart2.Left;
    width:=chart2.Width;
    height:=chart2.Height;
    FillStyle:=chart2.FillStyle;

    penStyle.Color:=ChartColorTo;
    penStyle.Opacity:=chart2.penStyle.Opacity;
    bgPatternColor:=ChartGridColor;
    bgStyle:=xhsDottedGrid; //xhsSmallGrid;
    bgOpacity:=0;
    BorderStyle.Enabled:=false;
    GradientStyle.ColorBegin:=ChartColor;
    GradientStyle.ColorEnd:=ChartColorTo;
    GradientStyle.Opacity:=chart2.GradientStyle.Opacity;
    GradientStyle.OpacityEnd:=chart2.GradientStyle.OpacityEnd;
  end;
  SetAllowMoveWidget(chart,true);
  case ChartInfoType of
    0: chart2.visible:=false; // CPU使用率
    1: chart2.visible:=true;  // CPU/内存使用率
    2: //网络流量
      begin
        chart2.visible:=true;
        chart.MaxValue:=MaxSpeed;
        chart2.MaxValue:=chart.MaxValue;
      end;
  end;
  if not chart2.visible then
    chart.bgOpacity:=10;
end;

procedure InitAll;
begin
  CurrentTop:=0;
  BeginUpdate;
  InitCores;
  InitMemory;
  InitDrives;
  iRefreshDrivesIntervalTimes:=9;
  InitNetwork;
  InitChart;
  imgbg.height:=CurrentTop+TextBottom;
  Widget.height:=imgbg.height;
  EndUpdateAll;
end;

procedure nShowClick(Sender : TObject);
var
  i:integer;
begin
  if TMenuItem(Sender).Name='nShowAllCore' then
    nShowCore.checked:=true;
  ShowCore:=nShowCore.checked;  
  ShowAllCore:=nShowAllCore.Checked;
  if not ShowCore then
  begin
    ShowAllCore:=false;
    nShowAllCore.Checked:=false;
  end;
  ShowMemory:=nShowMemory.Checked;  
  ShowNetwork:=nShowNetwork.Checked;  
  ShowDrives:=nShowDrives.Checked;  
  ShowChart:=nShowChart.Checked;
  SetSettingBool('ShowCore',ShowCore);
  SetSettingBool('ShowAllCore',ShowAllCore);
  SetSettingBool('ShowMemory',ShowMemory);
  SetSettingBool('ShowNetwork',ShowNetwork);
  SetSettingBool('ShowDrives',ShowDrives);
  SetSettingBool('ShowChart',ShowChart);
  if (ShowNetwork or (ChartInfoType=2)) and not System.Machine.Network.Active then
    System.Machine.Network.Active:=true;
  InitAll;
end;

procedure GetSkinSetting;
var
  ini:TIniFile;
begin
  if FileExists(WidgetPath+'images\bg\'+SkinName+'.ini') then
  begin
    ini:=TIniFile.Create(WidgetPath+'images\bg\'+SkinName+'.ini');
    with ini do
    try
      TitleSize:=ReadInteger('setting','TitleSize',8);        //标题文字大小
      TitleHeight:=ReadInteger('setting','TitleHeight',12);     //标题高度
      TitleColor:=StrToColor(ReadString('setting','TitleColor',''),$FFFFFF); //标题颜色
      TitleSep:=ReadInteger('setting','TitleSep',4);        //标题之前的间隔
      
      ItemSize:=ReadInteger('setting','ItemSize',6);         //子项文字大小
      ItemHeight:=ReadInteger('setting','ItemHeight',11);      //子项高度
      ItemColor:=StrToColor(ReadString('setting','ItemColor',''),$7F7F7F);  //子项颜色
      TextFont:=ReadString('setting','TextFont','');
      TextBlur:=ReadBool('setting','TextBlur',false);
      TextShadow:=ReadBool('setting','TextShadow',false);

      ChartColor:=StrToColor(ReadString('setting','ChartColor',''),$796004);    //曲线图颜色
      ChartColorTo:=StrToColor(ReadString('setting','ChartColorTo',''),$FED701);  //曲线图渐进颜色
      Chart2Color:=StrToColor(ReadString('setting','Chart2Color',''),$0F5EA9);   //第二个曲线图颜色
      Chart2ColorTo:=StrToColor(ReadString('setting','Chart2ColorTo',''),$0082FE); //第二个曲线图渐进颜色
      ChartGridColor:=StrToColor(ReadString('setting','ChartGridColor',''),$210122);//曲线背景颜色
      ChartHeight:=ReadInteger('setting','ChartHeight',30);
    finally
      free;
    end;
  end;
  else
  begin
    TitleSize:=8;        //标题文字大小
    TitleHeight:=12;     //标题高度
    TitleColor:=$FFFFFF; //标题颜色
    TitleSep:=4;        //标题之前的间隔
    
    ItemSize:=6;         //子项文字大小
    ItemHeight:=11;      //子项高度
    ItemColor:=$7F7F7F;  //子项颜色
    TextFont:='';
    TextBlur:=false;
    TextShadow:=false;
    
    ChartColor:=$796004;    //曲线图颜色
    ChartColorTo:=$FED701;  //曲线图渐进颜色
    Chart2Color:=$0F5EA9;   //第二个曲线图颜色
    Chart2ColorTo:=$0082FE; //第二个曲线图渐进颜色
    ChartGridColor:=$210122;//曲线背景颜色
    ChartHeight:=30;
  end;
end;

procedure ChangeSkin(Sender:TObject);
begin
  SkinName:=TMenuItem(Sender).caption;
  BeginUpdate;
  imgbg.FileName:=WidgetPath+'images\bg\'+SkinName+'.png';
  GetSkinSetting;
  InitAll;
  EndUpdate;
  SetSetting('SkinName',SkinName);
end;

procedure nChartShowClick(Sender : TObject);
var
  i:integer;
begin
  ChartInfoType:=TxspChart(Sender).tag;
  chart2.Clear;
  chart.Clear;
  if ChartInfoType=2 then
    chart.MaxValue:=MaxSpeed
  else
    chart.MaxValue:=100;
  chart2.MaxValue:=chart.MaxValue;
  SetSetting('ChartInfoType',ChartInfoType);  
end;

//读取配置
procedure InitIni;
var
  lst:TStrings;
  mi:TMenuItem;
  i:integer;
begin
  ShowCore:=GetSettingBool('ShowCore',true);
  ShowAllCore:=GetSettingBool('ShowAllCore',true);
  ShowMemory:=GetSettingBool('ShowMemory',true);
  ShowNetwork:=GetSettingBool('ShowNetwork',true);
  ShowDrives:=GetSettingBool('ShowDrives',true);
  ShowChart:=GetSettingBool('ShowChart',true);

  nShowCore.Checked:=ShowCore;
  nShowAllCore.Checked:=ShowAllCore;
  nShowMemory.Checked:=ShowMemory;
  nShowNetwork.Checked:=ShowNetwork;
  nShowDrives.Checked:=ShowDrives;
  nShowChart.Checked:=ShowChart;

  ChartInfoType:=GetSettingInt('ChartInfoType',2);
  case ChartInfoType of
    0: nChartShowCore.checked:=true;
    1: nChartShowAllCore.checked:=true;
    2: nChartShowNetwork.Checked:=true;
  end;

  SkinName:=GetSetting('SkinName','Blue');
  imgbg.FileName:=WidgetPath+'images\bg\'+SkinName+'.png';
  lst:=TStringList.create;
  try
    lst.text:=GetFileList(WidgetPath+'images\bg\','*.png',false,false,false);
    if lst.count>0 then
    	for i:=0 to lst.count-1 do
    	begin
        lst.strings[i]:=copy(lst.strings[i],1,length(lst.strings[i])-4);
  	    mi:=AddSkinMenuItem(lst.strings[i],i,'ChangeSkin');
  	    if mi.caption=SkinName then mi.checked:=true;
  	  end;
  finally
    lst.free;
  end;
  GetSkinSetting;

  NetDevice:=GetSetting('NetDevice','');
  MaxSpeed:=GetSettingInt('MaxSpeed',0);
  isAutoMaxSpeed:=GetSettingInt('NetType',0)=0;
  with System.Machine.Network do
  if NetDevice='' then
  begin
    if AvailableAdapterList.count>1 then
    begin
      NetDevice:=ActiveAdapterName;
      showtrayhint('警告','您的电脑有多个网络设备，如果默认的没有网速，请到小工具设置窗口选择你使用的网络设备！');
      SetSetting('NetDevice',NetDevice);
    end;
  end
  else
    System.Machine.Network.ActiveAdapterName:=NetDevice;
end;

//--- Widget初始化事件，当打开Widget时会触发此事件 ---
procedure OnWidgetInit;
begin
  Cores:=nil;  CoreValues:=nil;
  Drives:=nil; DriveValues:=nil;
  chart:=nil;  chart2:=nil;
  lblMemory:=nil; lblMemoryValue:=nil;  lblUsed:=nil;   lblUsedValue:=nil;
  lblFree:=nil;   lblFreeValue:=nil;    lblTotal:=nil;  lblTotalValue:=nil;
  lblNetwork:=nil; lblNetworkValue:=nil; lblIP:=nil;  lblIPValue:=nil;
  lblUp:=nil;  lblUpValue:=nil;  lblDown:=nil;lblDownValue:=nil;
  lblUpDownSize:=nil; lblUpDownSizeValue:=nil;
  iRefreshDrivesIntervalTimes:=0;
  PrevSpeed:=0;

  InitIni;

  if ShowCore or ShowMemory then
    StartCPUMemWatch;
  InitAll;

  if ShowNetwork or (ChartInfoType=2) then
    System.Machine.Network.Active:=true;

  tmr:=TTimer.Create(Widget);
  tmr.Interval:=1000;
  tmr.OnTimer:='OntmrTimer';

  AutoAdjustMem:=0;
  RefreshSidebarOrder;

end;

//--- Widget关闭事件，当关闭Widget时会触发此事件 ---
procedure OnWidgetClose;
begin
  System.Machine.Network.Active:=false;
  StopCPUMemWatch;
  if Cores<>nil then Cores.free;
  if CoreValues<>nil then CoreValues.free;
  if Drives<>nil then Drives.free;
  if DriveValues<>nil then DriveValues.free;
end;

//--- Widget移入边栏事件，当Widget被移到边栏上时会触发此事件 ---
procedure OnWidgetDock;
begin
  Widget.Width:=136;
end;

//--- Widget移出边栏事件，当Widget被移出边栏时会触发此事件 ---
procedure OnWidgetUnDock;
begin
  Widget.Width:=142;
end;

//刷新磁盘信息
procedure RefreshDrivesInfo;
var
  isReady:boolean;
  sVolume:string;
  iTotal,iFree,iPer,iType:Integer;
  sType,sDriveFormat:string;

  sTotal,sFree,sPer:string;

  iNum,i:integer;
  s:string;
begin
  iNum:=length(DriveName);
  if iNum<=0 then exit;
  for i:=1 to iNum do
  begin
    System.Shell.GetDriveInfo(DriveName[i],isReady,sVolume,iFree,iTotal,iPer,iType,sDriveFormat);
    sPer:=IntToStr(iPer);
    if length(sPer)=1 then sPer:='0'+sPer;
    sPer:=sPer+'%';
    sFree:=GetMSize(iFree);
    sUse:=GetMSize(iTotal-iFree);
    sTotal:=GetMSize(iTotal);
    TxspLabel(DriveValues.Objects[i]).caption:=sFree+' / '+sPer;

    if sVolume='' then
    begin
      sVolume:=DriveName[i]+':';
      sType:=DiskTypeToStr(iType);
    end
    else
      sType:=sVolume;
    TxspLabel(Drives.Objects[i]).caption:=sVolume;
    TxspLabel(DriveValues.Objects[i]).hint:=
      sType+'('+DriveName[i]+':)'+#13#10+
      format('已用：%s (%s)'#13#10,[sUse,sPer])+
      format('可用：%s (%s%s)'#13#10'总容量：%s'#13#10'文件系统：%s',[sfree,IntToStr(100-iPer),'%',sTotal,sDriveFormat]);
  end;
end;

function GetSize(value:Int64):string;
var
  i:integer;
  f:double;
  s:string;
begin
  //计算剩余容量
  i:=0;
  f:=value/1024;
  while f>1024 do
  begin
    inc(i);
    f:=f/1024;
  end;
  case i of
    0: s:='KB';
    1: s:='MB';
    2: s:='GB';
    3: s:='TB';
  else
    s:='MB';
  end;
  result:=format('%.1f %s',[f,s]);
end;

//Timer触发的事件
procedure OntmrTimer(sender);
var
  i,j:Int64;
  s:string;
begin
  BeginUpdate;
  if ShowCore then
  begin
    if CoreValues.count>0 then
    	TxspLabel(CoreValues.Objects[0]).caption:=inttostr(system.Machine.cpus.usagePercentage)+'%';
    if ShowAllCore and (CoreValues.count>=cpuCount) then
      for i:=1 to cpuCount do
      begin
    	  TxspLabel(CoreValues.Objects[i]).caption:=inttostr(system.Machine.cpus.items[i-1].usagePercentage)+'%';
      end;
  end;
  if ShowMemory then
  begin
    lblMemoryValue.caption:=IntToStr(round((TotalMem-system.Machine.availableMemory)*100/TotalMem))+'%';
    lblUsedValue.caption:=IntToStr(TotalMem-system.Machine.availableMemory)+'MB';
    lblFreeValue.caption:=IntToStr(system.Machine.availableMemory)+'MB';
  end;
  if ShowDrives then
  begin
    inc(iRefreshDrivesIntervalTimes);
    if (iRefreshDrivesIntervalTimes mod RefreshDrivesInterval=0) then
    begin
      iRefreshDrivesIntervalTimes:=0;
      RefreshDrivesInfo;
    end;
  end;
  if ShowNetwork then
  with System.Machine.Network do
  begin
    lblIPValue.caption:=IP;
    lblUpValue.caption:=GetSize(ActiveAdapter.OutPerSec)+'/s';
    lblDownValue.caption:=GetSize(ActiveAdapter.InPerSec)+'/s';
    lblUpDownSizeValue.caption:=GetSize(ActiveAdapter.OutTotal)+' / '+GetSize(ActiveAdapter.InTotal);
    lblDownValue.hint:=format('--- 下载 ---'#13#10'累计下载 : %s'#13#10'平均下载速度: %s/每秒'#13#10'最高下载速度: %s/每秒',
        [GetSize(ActiveAdapter.InTotal),GetSize(ActiveAdapter.AverageInPerSec), GetSize(ActiveAdapter.PeakInPerSec)]);
    lblUpValue.hint:=format('--- 上传 ---'#13#10'累计上传 :%s'#13#10'平均上传速度: %s/每秒'#13#10'最高上传速度: %s/每秒',
        [GetSize(ActiveAdapter.OutTotal),  GetSize(ActiveAdapter.AverageOutPerSec),GetSize(ActiveAdapter.PeakOutPerSec)]);
    lblIPValue.hint:=format('%s'#13#10'IP    地址 : %s'#13#10'网卡地址 : %s'#13#10'%s'#13#10'%s',
        [ActiveAdapterName,IP,MacAddress,lblDownValue.hint,lblUpValue.hint]);
    lblNetworkValue.hint:=lblIPValue.hint;
  end;
  if ShowChart then
  begin
    case ChartInfoType of
      0: //CPU
        begin
          chart.AddItem(system.Machine.cpus.usagePercentage);
          chart.hint:=format('CPU使用率：%d%%',[system.Machine.cpus.usagePercentage]);
        end;
      1: //CPU/Mem
        begin
          chart.AddItem(system.Machine.cpus.usagePercentage);
          chart2.AddItem(round((TotalMem-system.Machine.availableMemory)*100/TotalMem));
          chart.hint:=format('CPU使用率：%d%%'#13#10'内存使用率：%d%%',[system.Machine.cpus.usagePercentage,chart2.Percent]);
        end;
      2: //Network
        begin
          //下面两行用于平滑曲线
          chart.AddItem(round((PrevSpeed+System.Machine.Network.InPerSec)/2));
          PrevSpeed:=System.Machine.Network.InPerSec;
          //chart.AddItem(System.Machine.Network.InPerSec);
          chart2.AddItem(System.Machine.Network.OutPerSec);
  				with System.Machine.Network do
          	chart.hint:=format('%s'#13#10'IP    地址 : %s'#13#10'网卡地址 : %s'#13#10,[ActiveAdapterName,IP,MacAddress])+
            	format('--- 下载 ---'#13#10'累计下载 : %s'#13#10'平均下载速度: %s/每秒'#13#10'最高下载速度: %s/每秒'#13#10,
            	  [GetSize(ActiveAdapter.InTotal),GetSize(ActiveAdapter.AverageInPerSec), GetSize(ActiveAdapter.PeakInPerSec)])+
            	format('--- 上传 ---'#13#10'累计上传 :%s'#13#10'平均上传速度: %s/每秒'#13#10'最高上传速度: %s/每秒',
            	  [GetSize(ActiveAdapter.OutTotal),  GetSize(ActiveAdapter.AverageOutPerSec),GetSize(ActiveAdapter.PeakOutPerSec)]);
          
          if isAutoMaxSpeed then
          begin
            if MaxSpeed<System.Machine.Network.ActiveAdapter.PeakInPerSec then
            begin
              MaxSpeed:=System.Machine.Network.ActiveAdapter.PeakInPerSec;
              chart.MaxValue:=MaxSpeed;
              chart2.MaxValue:=chart.MaxValue;
              SetSettingInt('MaxSpeed',MaxSpeed);
            end;
          end;
        end;
    end;
  end;
  EndUpdate;
end;

