{******************************************************************}
{ TraffDlg.pas                                                     }
{                                                                  }
{ Author    : A.Nasir Senturk                                      }
{ Home Page : http://www.shenturk.com                              }
{ Email     : shenturk@gmail.com                                   }
{                                                                  }
{ Date      : 07.01.2007                                           }
{ Update    : 26.03.2007                                           }
{                                                                  }
{ Sizden iki şey rica edicem:                                      }
{ 1. Lutfen bu baslik kismini kaldirmayiniz.                       }
{ 2. Mumkunse bagis yapiniz.                                       }
{ *****************************************************************}

unit TraffDlg;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, GdipApi, GdipObj, DirectDraw, TextUtil, ExtCtrls, ConstDef,
  TrafficUnit, ActnList, Menus;

const
  MAX_DATA = 90;

type
  TDrawStyle = (dsLine, dsBar, dsBoth);
  TDrawStyles = set of TDrawStyle;

type
  TDataArray = array[0..MAX_DATA - 1] of Integer;

type
  TTrafficForm = class(TForm)
    BackgrndLbl: TLabel;
    CloseBtn: TButton;
    HeaderTextLbl: TLabel;
    Timer: TTimer;
    InGridLbl: TLabel;
    OutGridLbl: TLabel;
    TrafficActionList: TActionList;
    AlwaysTopAction: TAction;
    TrafficPopup: TPopupMenu;
    AlwaysTopMenu: TMenuItem;
    InAvgLbl: TLabel;
    OutAvgLbl: TLabel;
    InTitleLbl: TLabel;
    OutTitleLbl: TLabel;
    InBarLbl: TLabel;
    OutBarLbl: TLabel;
    SetBarAct: TAction;
    SetLineAct: TAction;
    SetBarMenu: TMenuItem;
    SetLineMenu: TMenuItem;
    Down0Lbl: TLabel;
    Down50Lbl: TLabel;
    Down100Lbl: TLabel;
    Up100Lbl: TLabel;
    Up50Lbl: TLabel;
    Up0Lbl: TLabel;
    MouseTimer: TTimer;
    HibernateAction: TAction;
    HibernateMenu: TMenuItem;
    N1: TMenuItem;
    HideAction: TAction;
    HideMenu: TMenuItem;
    MoveWithMenu: TMenuItem;
    NormalViewAct: TAction;
    BriefViewAct: TAction;
    N2: TMenuItem;
    NormalViewMenu: TMenuItem;
    BriefViewMenu: TMenuItem;
    TimeLabel: TLabel;
    AdapterLbl: TLabel;
    SetBothAct: TAction;
    SetBothMenu: TMenuItem;
    N3: TMenuItem;
    OptionsMenu: TMenuItem;
    ChooseAdapterAct: TAction;
    N4: TMenuItem;
    ChooseAdapterMenu: TMenuItem;
    MoveWithAct: TAction;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure CloseBtnClick(Sender: TObject);
    procedure TimerTimer(Sender: TObject);
    procedure AlwaysTopActionExecute(Sender: TObject);
    procedure SetBarActExecute(Sender: TObject);
    procedure SetLineActExecute(Sender: TObject);
    procedure MouseTimerTimer(Sender: TObject);
    procedure HibernateActionExecute(Sender: TObject);
    procedure HideActionExecute(Sender: TObject);
    procedure NormalViewActExecute(Sender: TObject);
    procedure BriefViewActExecute(Sender: TObject);
    procedure SetBothActExecute(Sender: TObject);
    procedure TrafficPopupPopup(Sender: TObject);
    procedure ChooseAdapterActExecute(Sender: TObject);
    procedure MoveWithActExecute(Sender: TObject);
  private
    { Private declarations }
    OpacityMin,
    OpacityMax,
    Opacity: Byte;
    MainBuffer: TGPBitmap;
    DrawCanvas: TGPGraphics;
    PrevFormStyle: Cardinal;
    ColorizedImage,
    OverlayImage,
    CloseImage,
    CancelImage,
    CancelImageEnter,
    CancelImageLeave: TGPBitmap;

    Updating: Boolean;
    Traffic: TTraffic;
    Adapter: Integer;
    BandWidthDown,
    BandWidthUp: Integer;

    InGridPen,
    InLinePen: TGPPen;
    InBackBrush: TGPSolidBrush;

    OutGridPen,
    OutLinePen: TGPPen;
    OutBackBrush: TGPSolidBrush;

    BarBackBrush,
    BarFillBrush,
    InBarBrush,
    OutBarBrush: TGPSolidBrush;

    InDataArray, OutDataArray: TDataArray;
    ShiftPos: Integer;
    DrawStyle: TDrawStyle;
    InPerSec,
    OutPerSec: Cardinal;
    procedure AllocateDrawItems;
    procedure ReleaseDrawItems;
    procedure AllocateHandle;
    procedure ReleaseHandle;
    procedure SetFormStyleEx;
  protected

  public
    { Public declarations }
    BackColor: Cardinal;
    BackOpacity: Byte;
    ViewStyle: TViewStyle;
    ScaleWidth,
    ScaleHeight: Single;
    InGridColor,
    InLineColor,
    InBackColor,
    OutGridColor,
    OutLineColor,
    OutBackColor: Cardinal;
    TextColor: TGPColor;
    procedure UpdateLayered;
    procedure UpdateMainWindow;
    procedure PaintBackground;
    procedure PaintButtons;
    procedure PaintHeaderText;
    procedure HideForm;
    procedure ShowForm;
    procedure HideFormEffect(const Min: Integer);
    procedure ShowFormEffect(const Max: Integer);
    procedure Hibernate;
    procedure Wakeup;
    procedure FadeInEffect(const Step, Wait, Max: Integer);
    procedure FadeOutEffect(const Step, Wait, Min: Integer);
    procedure InitTrafficForm;
    procedure DoneLoginForm;
    procedure LoadOptions;
    procedure SaveOptions;
    procedure SetWorkArea;
    procedure ProcessMIBData;
    procedure RefreshDisplay;
    procedure PaintInGrid;
    procedure PaintOutGrid;
    procedure ShiftData(var DataArray: TDataArray; Last: Integer);
    procedure PaintInData;
    procedure PaintOutData;
    procedure PaintInAverage;
    procedure PaintOutAverage;
    procedure PaintInTitle;
    procedure PaintOutTitle;
    procedure PaintInBar;
    procedure PaintOutBar;
    procedure SetColorsDrawItems;
    procedure LoadOptionsInterrupt;
    procedure SetNormalViewStyle;
    procedure SetBriefViewStyle;
    procedure SetViewStyle(const AViewStyle: TViewStyle);
    procedure ClearDataArray(var DataArray: TDataArray);
    procedure ClearDisplay;
    procedure ChangeAdapter;
    procedure PaintAdapter;
    procedure PaintTime;
    function GetAdapterText: WideString;
    function GetTimeText: WideString;
    procedure ChangeDrawingItems;
    procedure UpdateIniFile;
  end;

implementation

uses Main, OptnsDlg, IpHlpAPI, IPHelper, Math;

{$R *.dfm}

const
  CellWidth  = 8;
  CellHeight = 12;

{ TTrafficForm }

procedure TTrafficForm.AllocateHandle;
begin
  MainBuffer := TGPBitmap.Create(Width, Height, PixelFormat32bppARGB);
  DrawCanvas := TGPGraphics.Create(MainBuffer);
end;

procedure TTrafficForm.FadeInEffect(const Step, Wait, Max: Integer);
begin
  if not EyMainForm.EnableFadeEffect then Exit;
  while Opacity < Max do
  begin
    Application.ProcessMessages;
    if Opacity + Step >= Max then
    begin
      Opacity := Max;
      UpdateMainWindow;
      Break;
    end;
    Opacity := Opacity + Step;
    UpdateMainWindow;
    Sleep(Wait);
  end;
end;

procedure TTrafficForm.FadeOutEffect(const Step, Wait, Min: Integer);
begin
  if not EyMainForm.EnableFadeEffect then Exit;
  while Opacity > Min do
  begin
    Application.ProcessMessages;
    if Opacity - Step <= Min then
    begin
      Opacity := Min;
      UpdateMainWindow;
      Break;
    end;
    Opacity := Opacity - Step;
    UpdateMainWindow;
    Sleep(Wait);
  end;
end;

procedure TTrafficForm.HideForm;
begin
  HideFormEffect(OpacityMin);
  Self.Hide;
end;

procedure TTrafficForm.PaintBackground;

  procedure PaintColorizedOverlay;
  begin
    {
    DrawCanvas.DrawImage(OverlayImage,
      BackgrndLbl.Left + 6,
      BackgrndLbl.Top + 3,
      OverlayImage.GetWidth, OverlayImage.GetHeight);
    }
    DrawCanvas.DrawImage(OverlayImage,
      BackgrndLbl.Left + (7 * ScaleWidth) - ScaleWidth,
      BackgrndLbl.Top + (4 * ScaleHeight) - ScaleHeight + 0.15,
      OverlayImage.GetWidth * ScaleWidth,
      OverlayImage.GetHeight * ScaleHeight);
  end;

  procedure PaintColorized(Color: Cardinal; Alpha: Byte);
  const
    CMatrix: ColorMatrix = (
      (1.0, 0.0, 0.0, 0.0, 1.0),
      (0.0, 1.0, 0.0, 0.0, 0.0),
      (0.0, 0.0, 1.0, 0.0, 0.0),
      (0.0, 0.0, 0.0, 1.0, 0.0),
      (0.0, 0.0, 0.0, 0.0, 1.0)
    );
  var
    Attr: TGPImageAttributes;
    Matrix: ColorMatrix;
  begin

    Matrix := CMatrix;

    Matrix[3, 3] := (Alpha / 255);
    Matrix[0, 0] := 2 * (GetRValue(Color) / 255);
    Matrix[1, 1] := 2 * (GetGValue(Color) / 255);
    Matrix[2, 2] := 2 * (GetBValue(Color) / 255);

    Attr := TGPImageAttributes.Create;
    try
      Attr.SetColorMatrix(Matrix, ColorMatrixFlagsDefault, ColorAdjustTypeBitmap);

      DrawCanvas.DrawImage(ColorizedImage,
        MakeRect(BackgrndLbl.Left, BackgrndLbl.Top,
        ColorizedImage.GetWidth * ScaleWidth,
        ColorizedImage.GetHeight * ScaleHeight),  // dest rect
        0, 0, ColorizedImage.GetWidth, ColorizedImage.GetHeight,       // source rect
        UnitPixel,
        Attr);

      PaintColorizedOverlay;

    finally
      Attr.Free;
    end;

  end;

begin
  if BackgrndLbl.Visible then
    PaintColorized(BackColor, BackOpacity);
end;

procedure TTrafficForm.PaintHeaderText;
var
  WideText: WideString;
begin
  if HeaderTextLbl.Visible then
  begin
    WideText := 'Ağ Monitörü';
    PaintLabelTo(DrawCanvas, HeaderTextLbl, WideText, StringAlignmentNear, $FFFFFFFF);
  end;
end;

procedure TTrafficForm.ReleaseHandle;
begin
  if Assigned(MainBuffer) then FreeAndNil(MainBuffer);
  if Assigned(DrawCanvas) then FreeAndNil(DrawCanvas);
end;

procedure TTrafficForm.ShowForm;
begin
  case ViewStyle of
    vsBrief: SetBriefViewStyle;
  else SetNormalViewStyle;
  end;
  NormalViewAct.Checked := ViewStyle = vsNormal;
  BriefViewAct.Checked := ViewStyle = vsBrief;
  UpdateLayered;
  Self.Show;
  ShowFormEffect(OpacityMax);
end;

procedure TTrafficForm.UpdateLayered;
begin

  Updating := True;
  try
    ReleaseHandle;
    AllocateHandle;
    PaintBackground;
    PaintButtons;
    PaintHeaderText;
    PaintAdapter;
    //PaintTime;
    PaintInTitle;
    PaintTime;
    PaintInGrid;
    PaintInData;
    PaintInAverage;
    //PaintDivider;
    PaintOutTitle;
    PaintOutGrid;
    PaintOutData;
    PaintOutAverage;
    PaintInBar;
    PaintOutBar;
    UpdateMainWindow;
  finally
    Updating := False;
  end;
end;

procedure TTrafficForm.UpdateMainWindow;
var
  ScrDC, MemDC: HDC;
  BitmapHandle, PrevBitmap: HBITMAP;
  BlendFunc: _BLENDFUNCTION;
  Size: TSize;
  P, S: TPoint;
begin

  ScrDC := CreateCompatibleDC(0);
  MemDC := CreateCompatibleDC(ScrDC);

  MainBuffer.GetHBITMAP(0, BitmapHandle);
  PrevBitmap := SelectObject(MemDC, BitmapHandle);
  Size.cx := Width;
  Size.cy := Height;
  P := Point(Left, Top);
  S := Point(0, 0);

  with BlendFunc do
  begin
    BlendOp := AC_SRC_OVER;
    BlendFlags := 0;
    SourceConstantAlpha := Opacity;
    AlphaFormat := AC_SRC_ALPHA;
  end;

  UpdateLayeredWindow(Handle, ScrDC, @P, @Size, MemDC, @S, 0,
    @BlendFunc, ULW_ALPHA);

  SelectObject(MemDC, PrevBitmap);
  DeleteObject(BitmapHandle);

  DeleteDC(MemDC);
  DeleteDC(ScrDC);

end;

procedure TTrafficForm.FormCreate(Sender: TObject);
begin

  HibernateMenu.Caption := strHibernateMenu;

  ScaleWidth := 1.00;
  ScaleHeight := 1.10;

  SetFormStyleEx;

  Timer.Interval := 1000;
  Traffic := nil;

  CloseImage := TGPBitmap.Create(UIPath + CloseLeaveImage);
  CancelImageEnter := TGPBitmap.Create(UIPath + CancelEnterImage);
  CancelImageLeave := TGPBitmap.Create(UIPath + CancelLeaveImage);
  CancelImage := CancelImageLeave;

  ColorizedImage := TGPBitmap.Create(UIPath + Background6Image);
  OverlayImage := TGPBitmap.Create(UIPath + Overlay6Image);

  Self.Left := IniFile.ReadInteger(sNetworkMonitor, sLeft, 678);
  Self.Top := IniFile.ReadInteger(sNetworkMonitor, sTop, 175);
  Self.Width := Round(ColorizedImage.GetWidth * ScaleWidth);
  Self.Height := Round(ColorizedImage.GetHeight * ScaleHeight);

  LoadOptions;

  OpacityMin := DefOpacityMin;
  OpacityMax := DefOpacityMax;

  if EyMainForm.EnableFadeEffect then Opacity := OpacityMin
  else Opacity := OpacityMax;

  UpdateLayered;

  Timer.Enabled := True;

end;

procedure TTrafficForm.FormDestroy(Sender: TObject);
begin
  MouseTimer.OnTimer := nil;
  Timer.OnTimer := nil;
  SaveOptions;
  Traffic.Free;
  ReleaseDrawItems;
  CancelImageEnter.Free;
  CancelImageLeave.Free;
  CloseImage.Free;
  OverlayImage.Free;
  ColorizedImage.Free;
  ReleaseHandle;
end;

procedure TTrafficForm.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  R: TRect;
begin

  if (Button = mbLeft) and (ssShift in Shift) then
  begin
    HibernateActionExecute(Self);
    Exit;
  end;

  if Button = mbLeft then
  begin
    ReleaseCapture;
    SendMessage( Handle, WM_SYSCOMMAND, SC_DRAGMOVE, 0 );
    GetWindowRect(Handle, R);
    Left := R.Left;
    Top := R.Top;
    UpdateLayered;
  end;
end;

procedure TTrafficForm.InitTrafficForm;
begin
  LoadOptions;
end;

procedure TTrafficForm.DoneLoginForm;
begin
  SaveOptions;
end;

procedure TTrafficForm.HideFormEffect(const Min: Integer);
begin
  if EyMainForm.EnableFadeEffect then
    FadeOutEffect(DefOpacityStep, DefOpacityWait, Min)
  else begin
    Opacity := Min;
    UpdateMainWindow;
  end;
end;

procedure TTrafficForm.ShowFormEffect(const Max: Integer);
begin
  if EyMainForm.EnableFadeEffect then
    FadeInEffect(DefOpacityStep, DefOpacityWait, Max)
  else begin
    Opacity := Max;
    UpdateMainWindow;
  end;
end;

procedure TTrafficForm.Hibernate;
begin
  OpacityMax := DefOpacityMax div 2;
  HideFormEffect(OpacityMax);
end;

procedure TTrafficForm.Wakeup;
begin
  OpacityMax := DefOpacityMax;
  ShowFormEffect(OpacityMax);
end;

procedure TTrafficForm.PaintButtons;
begin
  if CloseBtn.Visible then
  begin
    DrawImageTo(DrawCanvas, CloseBtn.Left, CloseBtn.Top,
      CloseImage.GetWidth, CloseImage.GetHeight, CloseImage);
  end;
end;

procedure TTrafficForm.LoadOptions;
begin

  SetWorkArea;

  ReleaseDrawItems;

  ViewStyle := TViewStyle(IniFile.ReadInteger(sNetworkMonitor, sViewStyle,
    Integer(vsNormal)));

  DrawStyle := TDrawStyle(IniFile.ReadInteger(sNetworkMonitor, sLineStyle,
    Integer(dsLine)));

  Adapter := IniFile.ReadInteger(sNetworkMonitor, sAdapterIndex, 0);
  BandWidthDown := IniFile.ReadInteger(sNetworkMonitor, sBandWidthDown, 1024);
  if BandWidthDown <= 0 then BandWidthDown := 1024;
  BandWidthUp := IniFile.ReadInteger(sNetworkMonitor, sBandWidthUp, 256);
  if BandWidthUp <= 0 then BandWidthUp := 256;

  InGridColor := IniFile.ReadInteger(sNetworkMonitor, sInGridColor, Integer($8FA8A8A8));
  InLineColor := IniFile.ReadInteger(sNetworkMonitor, sDownLineColor, Integer($FF00FF00));
  InBackColor := IniFile.ReadInteger(sNetworkMonitor, sInBackColor, Integer($80000000));

  OutGridColor := IniFile.ReadInteger(sNetworkMonitor, sOutGridColor, Integer($8FA8A8A8));
  OutLineColor := IniFile.ReadInteger(sNetworkMonitor, sUpLineColor, Integer($FF0080FF));
  OutBackColor := IniFile.ReadInteger(sNetworkMonitor, sOutBackColor, Integer($80000000));

  BackColor := IniFile.ReadInteger(sNetworkMonitor, sBackColor, Integer($00C08000));
  BackOpacity := IniFile.ReadInteger(sNetworkMonitor, sBackOpacity, Integer($E0));
  TextColor := IniFile.ReadInteger(sNetworkMonitor, sTextColor, Integer($00FFFFFF));

  AllocateDrawItems;

end;

procedure TTrafficForm.SaveOptions;
begin
  IniFile.WriteInteger(sNetworkMonitor, sLeft, Left);
  IniFile.WriteInteger(sNetworkMonitor, sTop, Top);
end;

procedure TTrafficForm.CloseBtnClick(Sender: TObject);
begin
  EyMainForm.ShowTrafficAct.Checked := False;
  UpdateLayered;
  HideForm;
end;

procedure TTrafficForm.ProcessMIBData;
var
  MibArr: IpHlpAPI.TMIBIfArray;
begin
  if Adapter < 0 then Exit;
  Get_IfTableMIB(MibArr);
  if Assigned(Traffic) then
    if Traffic.Connected then Traffic.Found := False;
  if Length(MibArr) > 0 then
  begin
    if (Adapter >= Low(MibArr)) and (Adapter <= High(MibArr)) then
    begin
      if Assigned(Traffic) then
        Traffic.NewCycle(MIBArr[Adapter].dwInOctets,
          MIBArr[Adapter].dwOutOctets,
          MIBArr[Adapter].dwSpeed)
      else begin
        Traffic := TTraffic.Create(MIBArr[Adapter], nil);
        Traffic.Found := True;
      end;
      ShiftData(InDataArray, Traffic.InPerSec);
      ShiftData(OutDataArray, Traffic.OutPerSec);
    end;
  end;
  {
  if Assigned(Traffic) then
    if not Traffic.Found then
      Traffic.MarkDisconnected;
  }
  RefreshDisplay;
end;

procedure TTrafficForm.TimerTimer(Sender: TObject);
begin
  Timer.Enabled := False;
  Dec(ShiftPos, 2);
  if ShiftPos = -CellWidth then ShiftPos := 0;
  ProcessMIBData;
  Timer.Enabled := True;
end;

procedure TTrafficForm.RefreshDisplay;
const
  sAvgFmt = 'Ortalama: %s/s';
  sPeakFmt = 'Anlık: %s/s';
var
  AnyText: WideString;
begin
  if not Self.Visible then Exit;
  if not Assigned(Traffic) then Exit;
  with Traffic do begin
    Self.InPerSec := InPerSec;
    Self.OutPerSec := OutPerSec;
    AnyText := WideFormat(sAvgFmt, [BytesToFriendlyString(AverageInPerSec)]) + '  ' +
               WideFormat(sPeakFmt, [BytesToFriendlyString(InPerSec)]);
    InAvgLbl.Caption := AnyText;
    AnyText := WideFormat(sAvgFmt, [BytesToFriendlyString(AverageOutPerSec)]) + '  ' +
               WideFormat(sPeakFmt, [BytesToFriendlyString(OutPerSec)]);
    OutAvgLbl.Caption := AnyText;
    InTitleLbl.Caption := ' Download: ' + BytesToFriendlyString(InTotal);
    OutTitleLbl.Caption := ' Upload: ' + BytesToFriendlyString(OutTotal);
    if not AdapterLbl.ShowHint then
    begin
      AdapterLbl.Hint := Traffic.Description;
      AdapterLbl.ShowHint := True;
    end;
  end;
  UpdateLayered;
end;

procedure TTrafficForm.SetFormStyleEx;
var
  StyleEx: Cardinal;
begin
  StyleEx := GetWindowLong(Handle, GWL_EXSTYLE);
  if StyleEx and WS_EX_LAYERED = 0 then
    SetWindowLong(Handle, GWL_EXSTYLE, StyleEx or WS_EX_LAYERED);
end;

procedure TTrafficForm.PaintInGrid;
var
  X, Y, W, H: Integer;

  procedure PaintPercents;
  begin
    PaintLabelTo(DrawCanvas, Down0Lbl, Down0Lbl.Caption,
      StringAlignmentFar, ColorRefToARGB(TextColor), True,
      TextRenderingHintAntiAliasGridFit);
    PaintLabelTo(DrawCanvas, Down50Lbl, Down50Lbl.Caption,
      StringAlignmentFar, ColorRefToARGB(TextColor), True,
      TextRenderingHintAntiAliasGridFit);
    PaintLabelTo(DrawCanvas, Down100Lbl, Down100Lbl.Caption,
      StringAlignmentFar, ColorRefToARGB(TextColor), True,
      TextRenderingHintAntiAliasGridFit);
  end;

begin
  DrawCanvas.FillRectangle(InBackBrush, MakeRect(InGridLbl.BoundsRect));
  DrawCanvas.DrawRectangle(InGridPen, MakeRect(InGridLbl.BoundsRect));
  PaintPercents;
  X := InGridLbl.Left + ShiftPos;
  Y := InGridLbl.Top;
  W := InGridLbl.Left + InGridLbl.Width;
  while X < W do begin
    if X > InGridLbl.Left then
      DrawCanvas.DrawLine(InGridPen, X, Y, X, Y + InGridLbl.Height - 1);
    Inc(X, CellWidth);
  end;
  X := InGridLbl.Left;
  H := InGridLbl.Top + InGridLbl.Height;
  while Y < H do begin
    DrawCanvas.DrawLine(InGridPen, X, Y, X + InGridLbl.Width - 1, Y);
    Inc(Y, CellHeight);
  end;
end;

procedure TTrafficForm.AllocateDrawItems;
begin
  InGridPen := TGPPen.Create(InGridColor);
  InLinePen := TGPPen.Create(ColorRefToARGB(InLineColor));
  InBackBrush := TGPSolidBrush.Create(InBackColor);
  OutGridPen := TGPPen.Create(OutGridColor);
  OutLinePen := TGPPen.Create(ColorRefToARGB(OutLineColor));
  OutBackBrush := TGPSolidBrush.Create(OutBackColor);
  BarBackBrush := TGPSolidBrush.Create($DC000000);
  BarFillBrush := TGPSolidBrush.Create($60A0A0A0);
  InBarBrush := TGPSolidBrush.Create($DC00FF00);
  OutBarBrush := TGPSolidBrush.Create($DC0000FF);
end;

procedure TTrafficForm.ReleaseDrawItems;
begin
  if Assigned(InBarBrush) then FreeAndNil(InBarBrush);
  if Assigned(OutBarBrush) then FreeAndNil(OutBarBrush);
  if Assigned(BarBackBrush) then FreeAndNil(BarBackBrush);
  if Assigned(BarFillBrush) then FreeAndNil(BarFillBrush);
  if Assigned(InGridPen) then FreeAndNil(InGridPen);
  if Assigned(InLinePen) then FreeAndNil(InLinePen);
  if Assigned(InBackBrush) then FreeAndNil(InBackBrush);
  if Assigned(OutGridPen) then FreeAndNil(OutGridPen);
  if Assigned(OutLinePen) then FreeAndNil(OutLinePen);
  if Assigned(OutBackBrush) then FreeAndNil(OutBackBrush);
end;

procedure TTrafficForm.PaintOutGrid;
var
  X, Y, W, H: Integer;

  procedure PaintPercents;
  begin
    PaintLabelTo(DrawCanvas, Up0Lbl, Up0Lbl.Caption,
      StringAlignmentFar, ColorRefToARGB(TextColor), True,
      TextRenderingHintAntiAliasGridFit);
    PaintLabelTo(DrawCanvas, Up50Lbl, Up50Lbl.Caption,
      StringAlignmentFar, ColorRefToARGB(TextColor), True,
      TextRenderingHintAntiAliasGridFit);
    PaintLabelTo(DrawCanvas, Up100Lbl, Up100Lbl.Caption,
      StringAlignmentFar, ColorRefToARGB(TextColor), True,
      TextRenderingHintAntiAliasGridFit);
  end;

begin
  DrawCanvas.FillRectangle(OutBackBrush, MakeRect(OutGridLbl.BoundsRect));
  DrawCanvas.DrawRectangle(OutGridPen, MakeRect(OutGridLbl.BoundsRect));
  PaintPercents;
  X := OutGridLbl.Left + ShiftPos;
  Y := OutGridLbl.Top;
  W := OutGridLbl.Left + OutGridLbl.Width;
  while X < W do begin
    if X > OutGridLbl.Left then
      DrawCanvas.DrawLine(OutGridPen, X, Y, X, Y + OutGridLbl.Height - 1);
    Inc(X, CellWidth);
  end;
  X := OutGridLbl.Left;
  H := OutGridLbl.Top + InGridLbl.Height;
  while Y < H do begin
    DrawCanvas.DrawLine(OutGridPen, X, Y, X + OutGridLbl.Width - 1, Y);
    Inc(Y, CellHeight);
  end;
end;

procedure TTrafficForm.ShiftData(var DataArray: TDataArray; Last: Integer);
var
  Index: Integer;
begin
  for Index := 0 to MAX_DATA - 2 do
    DataArray[Index] := DataArray[Index + 1];
  DataArray[MAX_DATA - 1] := Last;
end;

procedure TTrafficForm.PaintInData;
var
  X, Y: Integer;
  MaxHeight: Integer;

  procedure PaintInDataBar(Data: Integer);
  var
    H: Single;
  begin
    //H := InGridLbl.Height * ( ( Data / ( ( 1024 div 8 ) * 1024 ) ) );
    if Data < 0 then Data := 0;
    H := InGridLbl.Height * ( Data / ( BandWidthDown * 128 ) );
    H := Math.Min(H, MaxHeight);
    DrawCanvas.DrawLine(InLinePen, X, Y, X, Y - Round(H));
  end;

  procedure PaintInDataLine(Data1, Data2: Integer);
  var
    H1, H2: Single;
  begin
    //H := InGridLbl.Height * ( ( Data / ( ( 1024 div 8 ) * 1024 ) ) );
    if Data1 < 0 then Data1 := 0;
    H1 := InGridLbl.Height * ( Data1 / ( BandWidthDown * 128 ) );
    H1 := Math.Min(H1, MaxHeight);
    if Data2 < 0 then Data2 := 0;
    H2 := InGridLbl.Height * ( Data2 / ( BandWidthDown * 128 ) );
    H2 := Math.Min(H2, MaxHeight);
    DrawCanvas.DrawLine(InLinePen, X, Y - Round(H1), X + 2, Y - Round(H2));
  end;

  procedure DrawLineStyle;
  var
    Index: Integer;
  begin
    for Index := 0 to MAX_DATA - 1 do
    begin
      if Index >= MAX_DATA - 1 then Break;
      PaintInDataLine(InDataArray[Index], InDataArray[Index + 1]);
      Inc(X, 2);
    end;
  end;

  procedure DrawBarStyle;
  var
    Index: Integer;
  begin
    for Index := 0 to MAX_DATA - 1 do
    begin
      PaintInDataBar(InDataArray[Index]);
      Inc(X, 2);
    end;
  end;

  procedure DrawBothStyle;
  var
    Index: Integer;
  begin
    for Index := 0 to MAX_DATA - 1 do
    begin
      PaintInDataBar(InDataArray[Index]);
      if Index >= MAX_DATA - 1 then Break;
      PaintInDataLine(InDataArray[Index], InDataArray[Index + 1]);
      Inc(X, 2);
    end;
  end;

begin
  MaxHeight := InGridLbl.Height - 2;
  X := InGridLbl.Left + 1;
  Y := InGridLbl.Top + InGridLbl.Height - 1;
  case DrawStyle of
    dsBar  : DrawBarStyle;
    dsBoth : DrawBothStyle;
    else DrawLineStyle;
  end;
end;

procedure TTrafficForm.PaintOutData;
var
  X, Y: Integer;
  MaxHeight: Integer;

  procedure PaintOutDataBar(Data: Integer);
  var
    H: Single;
  begin
    //H := OutGridLbl.Height * ( Data / ( ( ( 256 ) div 8 ) * 1024 ) );
    if Data < 0 then Data := 0;
    H := OutGridLbl.Height * ( Data / ( BandWidthUp * 128 ) );
    H := Math.Min(H, MaxHeight);
    DrawCanvas.DrawLine(OutLinePen, X, Y, X, Y - Round(H));
  end;

  procedure PaintOutDataLine(Data1, Data2: Integer);
  var
    H1, H2: Single;
  begin
    //H := OutGridLbl.Height * ( ( Data / ( ( 256 div 8 ) * 1024 ) ) );
    if Data1 < 0 then Data1 := 0;
    H1 := OutGridLbl.Height * ( Data1 / ( BandWidthUp * 128 ) );
    H1 := Math.Min(H1, MaxHeight);
    if Data2 < 0 then Data2 := 0;
    H2 := OutGridLbl.Height * ( Data2 / ( BandWidthUp * 128 ) );
    H2 := Math.Min(H2, MaxHeight);
    DrawCanvas.DrawLine(OutLinePen, X, Y - Round(H1), X + 2, Y - Round(H2));
  end;

  procedure DrawLineStyle;
  var
    Index: Integer;
  begin
    for Index := 0 to MAX_DATA - 1 do
    begin
      if Index >= MAX_DATA - 1 then Break;
      PaintOutDataLine(OutDataArray[Index], OutDataArray[Index + 1]);
      Inc(X, 2);
    end;
  end;

  procedure DrawBarStyle;
  var
    Index: Integer;
  begin
    for Index := 0 to MAX_DATA - 1 do
    begin
      PaintOutDataBar(OutDataArray[Index]);
      Inc(X, 2);
    end;
  end;

  procedure DrawBothStyle;
  var
    Index: Integer;
  begin
    for Index := 0 to MAX_DATA - 1 do
    begin
      PaintOutDataBar(OutDataArray[Index]);
      if Index >= MAX_DATA - 1 then Break;
      PaintOutDataLine(OutDataArray[Index], OutDataArray[Index + 1]);
      Inc(X, 2);
    end;
  end;

begin
  MaxHeight := OutGridLbl.Height - 2;
  X := OutGridLbl.Left + 1;
  Y := OutGridLbl.Top + OutGridLbl.Height - 1;
  case DrawStyle of
    dsBar  : DrawBarStyle;
    dsBoth : DrawBothStyle;
    else DrawLineStyle;
  end;
end;

procedure TTrafficForm.AlwaysTopActionExecute(Sender: TObject);
var
  Style: Cardinal;
begin

  AlwaysTopAction.Checked := not AlwaysTopAction.Checked;
  {
  Style := GetWindowLong(Self.Handle, GWL_EXSTYLE);
  if AlwaysTopAction.Checked then
    Self.FormStyle := fsStayOnTop
  else Self.FormStyle := fsNormal;
  SetWindowLong(Self.Handle, GWL_EXSTYLE, Style);
  }
  if AlwaysTopAction.Checked then Style := HWND_TOPMOST //HWND_TOP or 
  else Style := HWND_NOTOPMOST;
  {
  SetWindowPos(Application.Handle, Style, 0, 0, 0, 0, SWP_NOMOVE or
      SWP_NOSIZE or SWP_FRAMECHANGED);
  }
  SetWindowPos(Self.Handle, Style, 0, 0, 0, 0, SWP_NOMOVE or
    SWP_NOSIZE or SWP_FRAMECHANGED);

end;

procedure TTrafficForm.PaintInAverage;
var
  R: TRect;
begin
  if InAvgLbl.Visible then
  begin
    R := InAvgLbl.BoundsRect;
    OffsetRect(R, 0, -1);
    DrawCanvas.FillRectangle(InBackBrush, MakeRect(R));
    DrawCanvas.DrawRectangle(InGridPen, MakeRect(R));
    PaintLabelTo(DrawCanvas, InAvgLbl, InAvgLbl.Caption,
      StringAlignmentNear, ColorRefToARGB(TextColor), True,
      TextRenderingHintAntiAliasGridFit);
  end;
end;

procedure TTrafficForm.PaintOutAverage;
var
  R: TRect;
begin
  if OutAvgLbl.Visible then
  begin
    R := OutAvgLbl.BoundsRect;
    OffsetRect(R, 0, -1);
    DrawCanvas.FillRectangle(OutBackBrush, MakeRect(R));
    DrawCanvas.DrawRectangle(OutGridPen, MakeRect(R));
    PaintLabelTo(DrawCanvas, OutAvgLbl, OutAvgLbl.Caption,
      StringAlignmentNear, ColorRefToARGB(TextColor), True,
      TextRenderingHintAntiAliasGridFit);
  end;
end;

procedure TTrafficForm.PaintInTitle;
begin
  if InTitleLbl.Visible then
  begin
    DrawCanvas.FillRectangle(InBackBrush, MakeRect(InTitleLbl.BoundsRect));
    DrawCanvas.DrawRectangle(InGridPen, MakeRect(InTitleLbl.BoundsRect));
    PaintLabelTo(DrawCanvas, InTitleLbl, InTitleLbl.Caption,
      StringAlignmentNear, ColorRefToARGB(TextColor), True,
      TextRenderingHintAntiAliasGridFit);
  end;
end;

procedure TTrafficForm.PaintOutTitle;
begin
  if OutTitleLbl.Visible then
  begin
    DrawCanvas.FillRectangle(OutBackBrush, MakeRect(OutTitleLbl.BoundsRect));
    DrawCanvas.DrawRectangle(OutGridPen, MakeRect(OutTitleLbl.BoundsRect));
    PaintLabelTo(DrawCanvas, OutTitleLbl, OutTitleLbl.Caption,
      StringAlignmentNear, ColorRefToARGB(TextColor), True,
      TextRenderingHintAntiAliasGridFit);
  end;
end;

procedure TTrafficForm.PaintInBar;
const
  BarCount = 16;
var
  X, Y, W, H: Integer;
  Percent, Index: Integer;
  Colorize: Cardinal;
begin
  DrawCanvas.FillRectangle(InBackBrush, MakeRect(InBarLbl.BoundsRect));
  DrawCanvas.DrawRectangle(InGridPen, MakeRect(InBarLbl.BoundsRect));
  W := 8;
  H := 2;
  X := InBarLbl.Left + (InBarLbl.Width - W) div 2 + 1;
  Y := InBarLbl.Top + 1;
  Index := BarCount;
  Percent := Round(BarCount * (InPerSec / (BandwidthDown * 128)));
  Percent := Math.Min(Percent, BarCount);
  //if Percent > BarCount then Percent := BarCount;
  while Y < InBarLbl.Top + InBarLbl.Height do
  begin
    if Index > Percent then
      DrawCanvas.FillRectangle(BarFillBrush, MakeRect(X, Y, W, H))
    else begin
      Colorize := MakeColor($FF, $FF, $FF - (($FF div BarCount) * Index), 0);
      InBarBrush.SetColor(Colorize);
      DrawCanvas.FillRectangle(InBarBrush, MakeRect(X, Y, W, H));
    end;
    Inc(Y, H + 1);
    Dec(Index);
  end;

end;

procedure TTrafficForm.PaintOutBar;
const
  BarCount = 16;
var
  X, Y, W, H: Integer;
  Percent, Index: Integer;
  Colorize: Cardinal;
begin
  DrawCanvas.FillRectangle(OutBackBrush, MakeRect(OutBarLbl.BoundsRect));
  DrawCanvas.DrawRectangle(OutGridPen, MakeRect(OutBarLbl.BoundsRect));
  W := 8;
  H := 2;
  X := OutBarLbl.Left + (OutBarLbl.Width - W) div 2 + 1;
  Y := OutBarLbl.Top + 1;
  Index := BarCount;
  Percent := Round(BarCount * (OutPerSec / (BandwidthUp * 128)));
  Percent := Math.Min(Percent, BarCount);
  //if Percent > BarCount then Percent := BarCount;
  while Y < OutBarLbl.Top + OutBarLbl.Height do
  begin
    if Index > Percent then
      DrawCanvas.FillRectangle(BarFillBrush, MakeRect(X, Y, W, H))
    else begin
      Colorize := MakeColor($FF, $FF, $FF - (($FF div BarCount) * Index), 0);
      OutBarBrush.SetColor(Colorize);
      DrawCanvas.FillRectangle(OutBarBrush, MakeRect(X, Y, W, H));
    end;
    Inc(Y, H + 1);
    Dec(Index);
  end;
end;

procedure TTrafficForm.SetColorsDrawItems;
begin
  InGridPen.SetColor(InGridColor);
  InLinePen.SetColor(ColorRefToARGB(InLineColor));
  InBackBrush.SetColor(InBackColor);
  OutGridPen.SetColor(OutGridColor);
  OutLinePen.SetColor(ColorRefToARGB(OutLineColor));
  OutBackBrush.SetColor(OutBackColor);
end;

procedure TTrafficForm.SetBarActExecute(Sender: TObject);
begin
  DrawStyle := dsBar;
  UpdateIniFile;
end;

procedure TTrafficForm.SetLineActExecute(Sender: TObject);
begin
  DrawStyle := dsLine;
  UpdateIniFile;
end;

procedure TTrafficForm.LoadOptionsInterrupt;
begin
  Timer.Enabled := False;
  LoadOptions;
  UpdateLayered;
  Timer.Enabled := True;
end;

procedure TTrafficForm.MouseTimerTimer(Sender: TObject);
var
  P: TPoint;
begin
  GetCursorPos(P);
  if PtInRect(Self.BoundsRect, P) then
  begin
    if (GetKeyState(VK_CONTROL) and $8000) <> 0 then
      HibernateActionExecute(Sender);
  end;
end;

procedure TTrafficForm.HibernateActionExecute(Sender: TObject);
begin
  if EyMainForm.AlertShow then Exit;
  HibernateAction.Checked := not HibernateAction.Checked;
  if HibernateAction.Checked then
  begin
    PrevFormStyle := GetWindowLong(Self.Handle, GWL_EXSTYLE);
    if PrevFormStyle and WS_EX_TRANSPARENT = 0 then
    begin
      EyMainForm.CheckHibernateAlert;
      Hibernate;
      SetWindowLong(Self.Handle, GWL_EXSTYLE, PrevFormStyle or WS_EX_TRANSPARENT);
      MouseTimer.Enabled := True;
    end;
  end
  else if PrevFormStyle <> 0 then begin
    MouseTimer.Enabled := False;
    Wakeup;
    SetWindowLong(Self.Handle, GWL_EXSTYLE, PrevFormStyle);
  end;
end;

procedure TTrafficForm.HideActionExecute(Sender: TObject);
begin
  EyMainForm.ShowTrafficActExecute(Sender);
end;

procedure TTrafficForm.NormalViewActExecute(Sender: TObject);
begin
  if ViewStyle <> vsNormal then SetViewStyle(vsNormal);
end;

procedure TTrafficForm.BriefViewActExecute(Sender: TObject);
begin
  if ViewStyle <> vsBrief then SetViewStyle(vsBrief);
end;

procedure TTrafficForm.SetBriefViewStyle;

  procedure SetupBriefBounds;
  begin
    //Self.Width := 239;
    //Self.Height := 227;
    Self.Width := Round(ColorizedImage.GetWidth * ScaleWidth);
    Self.Height := Round(ColorizedImage.GetHeight * ScaleHeight);
    {
    if Self.Left + Self.Width > Screen.WorkAreaWidth then
      Self.Left := Screen.WorkAreaWidth - Self.Width;
    if Self.Top + Self.Height > Screen.WorkAreaHeight then
      Self.Top := Screen.WorkAreaHeight - Self.Height;
    }
    SetWorkArea;
  end;

begin
  BackgrndLbl.Visible := False;
  HeaderTextLbl.Visible := False;
  CloseBtn.Visible := False;
  Down100Lbl.Visible := False;
  Down50Lbl.Visible := False;
  Down0Lbl.Visible := False;
  Up100Lbl.Visible := False;
  Up50Lbl.Visible := False;
  Up0Lbl.Visible := False;
  AdapterLbl.Visible := False;
  //TimeLabel.Visible := False;
  SetupBriefBounds;
end;

procedure TTrafficForm.SetNormalViewStyle;

  procedure SetupNormalBounds;
  begin
    //Self.Width := 239;
    //Self.Height := 227;
    Self.Width := Round(ColorizedImage.GetWidth * ScaleWidth);
    Self.Height := Round(ColorizedImage.GetHeight * ScaleHeight);
    {
    if Self.Left + Self.Width > Screen.WorkAreaWidth then
      Self.Left := Screen.WorkAreaWidth - Self.Width;
    if Self.Top + Self.Height > Screen.WorkAreaHeight then
      Self.Top := Screen.WorkAreaHeight - Self.Height;
    }
    SetWorkArea;
  end;

begin
  BackgrndLbl.Visible := True;
  HeaderTextLbl.Visible := True;
  CloseBtn.Visible := True;
  {
  Down100Lbl.Visible := True;
  Down50Lbl.Visible := True;
  Down0Lbl.Visible := True;
  Up100Lbl.Visible := True;
  Up50Lbl.Visible := True;
  Up0Lbl.Visible := True;
  }
  AdapterLbl.Visible := True;
  TimeLabel.Visible := True;
  SetupNormalBounds;
end;

procedure TTrafficForm.SetViewStyle(const AViewStyle: TViewStyle);
begin
  ViewStyle := AViewStyle;
  HideForm;
  IniFile.WriteInteger(sNetworkMonitor, sViewStyle, Integer(ViewStyle));
  IniFile.UpdateFile;
  NormalViewAct.Checked := ViewStyle = vsNormal;
  BriefViewAct.Checked := ViewStyle = vsBrief;
  case ViewStyle of
    vsBrief: SetBriefViewStyle;
  else SetNormalViewStyle;
  end;
  UpdateLayered;
  ShowForm;
end;

procedure TTrafficForm.ChangeAdapter;
begin
  if Adapter < 0 then Exit;
  Timer.Enabled := False;
  ClearDisplay;
  if Assigned(Traffic) then FreeAndNil(Traffic);
  Timer.Enabled := True;
end;

procedure TTrafficForm.ClearDisplay;
begin
  ClearDataArray(InDataArray);
  ClearDataArray(OutDataArray);
  InPerSec := 0;
  OutPerSec := 0;
  AdapterLbl.ShowHint := False;
  AdapterLbl.Hint := '';
end;

procedure TTrafficForm.ClearDataArray(var DataArray: TDataArray);
var
  Index: Integer;
begin
  for Index := 0 to MAX_DATA - 1 do DataArray[Index] := 0;
end;

procedure TTrafficForm.SetBothActExecute(Sender: TObject);
begin
  DrawStyle := dsBoth;
  UpdateIniFile;
end;

procedure TTrafficForm.PaintAdapter;
var
  AnyText: WideString;
begin
  if AdapterLbl.Visible then
  begin
    DrawCanvas.FillRectangle(InBackBrush, MakeRect(AdapterLbl.BoundsRect));
    DrawCanvas.DrawRectangle(InGridPen, MakeRect(AdapterLbl.BoundsRect));
    AnyText := GetAdapterText();
    PaintLabelTo(DrawCanvas, AdapterLbl, AnyText,
      StringAlignmentNear, ColorRefToARGB(TextColor), True,
      TextRenderingHintAntiAliasGridFit);
  end;
end;

procedure TTrafficForm.PaintTime;
var
  AnyText: WideString;
begin
  if TimeLabel.Visible then
  begin
    //DrawCanvas.FillRectangle(InBackBrush, MakeRect(TimeLabel.BoundsRect));
    //DrawCanvas.DrawRectangle(InGridPen, MakeRect(TimeLabel.BoundsRect));
    AnyText := GetTimeText();
    PaintLabelTo(DrawCanvas, TimeLabel, AnyText,
      StringAlignmentFar, ColorRefToARGB(TextColor), True,
      TextRenderingHintAntiAliasGridFit);
  end;
end;

function TTrafficForm.GetAdapterText: WideString;
begin
  if Assigned(Traffic) then
    Result := ' ' + Traffic.Description
  else Result := 'Bağdaştırıcı seçilmemiş';
end;

function TTrafficForm.GetTimeText: WideString;
begin
  if Assigned(Traffic) then
    Result := ' ' + Traffic.FriendlyRunningTime
  else Result := 'Durmuş'; //'Monitör aktif değil.';
end;

procedure TTrafficForm.ChangeDrawingItems;
begin
  Timer.Enabled := False;
  SetColorsDrawItems;
  Timer.Enabled := True;
end;

procedure TTrafficForm.TrafficPopupPopup(Sender: TObject);
begin
  SetLineAct.Checked := DrawStyle = dsLine;
  SetBarAct.Checked := DrawStyle = dsBar;
  SetBothAct.Checked := DrawStyle = dsBoth;
  MoveWithAct.Checked := EyMainForm.TrafficWith;
end;

procedure TTrafficForm.UpdateIniFile;
begin
  IniFile.WriteInteger(sNetworkMonitor, sLeft, Left);
  IniFile.WriteInteger(sNetworkMonitor, sTop, Top);
  IniFile.WriteInteger(sNetworkMonitor, sLineStyle, Integer(DrawStyle));
  IniFile.WriteBool(sNetworkMonitor, sMoveWith, MoveWithAct.Checked);
  IniFile.UpdateFile;
end;

procedure TTrafficForm.SetWorkArea;
var
  R: TRect;
begin
  IntersectRect(R, Screen.WorkAreaRect, Self.BoundsRect);
  if IsRectEmpty(R) then
  begin
    Self.Left := Screen.WorkAreaWidth - Self.Width;
    Self.Top := Screen.WorkAreaHeight - Self.Height;
  end;
end;

procedure TTrafficForm.ChooseAdapterActExecute(Sender: TObject);
begin
  EyMainForm.ShowOptionsDialog(3);
end;

procedure TTrafficForm.MoveWithActExecute(Sender: TObject);
begin
  MoveWithAct.Checked := not MoveWithAct.Checked;
  EyMainForm.TrafficWith := MoveWithAct.Checked;
  UpdateIniFile;
end;

end.

