unit WidgetMain;

(*
<a href="http://whos.amung.us/stats/75t8h6jqah6v/">
<img src="http://whos.amung.us/widget/75t8h6jqah6v.png"
width="81" height="29" border="0"
title="Click to see how many people are online" /></a>
*)

interface

uses
  Windows, Messages, SysUtils, Classes, CommCtrl, ComObj, ActiveX, Widgets,
  GdipApi, WinInet, InetThrd, GdipObj, Contnrs, WIniFiles, MMSystem, InetUtil,
  WStrings, ShellApi, ShlObj;

const
  WM_VERSIONDONE    = WM_USER + $11;
  WM_THREADDONE     = WM_USER + $12;
  WM_HIDEFORM       = WM_USER + $13;
  WM_SHOWFORM       = WM_USER + $14;
  WM_ALWAYSTOP      = WM_USER + $15;
  WM_DETAILS        = WM_USER + $16;
  WM_DELETEWIDGET   = WM_USER + $18;
  WM_CHANGELANG     = WM_USER + $19;

  INTERVAL_MIN      = 7000;
  INTERVAL_DISABLE  = 0;
  {
  IDS_TRAY_TIP0 = 1000;
  IDS_TRAY_TIP1 = 1001;
  IDS_TRAY_TIP2 = 1002;
  }
  IDS_TEXT_1003 = 1003;
  IDS_TEXT_1004 = 1004;
  IDS_TEXT_1005 = 1005;
  IDS_TEXT_1006 = 1006;
  IDS_TEXT_1007 = 1007;
  IDS_TEXT_1008 = 1008;
  IDS_TEXT_1009 = 1009;
  IDS_TEXT_1010 = 1010;
  IDS_TEXT_1011 = 1011;


const
  CBtnChecks: array[Boolean] of Integer = (BST_UNCHECKED, BST_CHECKED);
  CChecks: array[Boolean] of Integer = (MF_UNCHECKED, MF_CHECKED);
  CChangeImages: array[-1..+1] of WideString = ('DEC.PNG', 'EQUAL.PNG', 'INC.PNG');
  CStateImages: array[Boolean] of WideString = ('IDLE.PNG', 'BUSY.PNG');

type
  { Forward Declation }
  TWidgetImageControl = class;
  TWidgetLabel = class;
  TWidgetManager = class;

  { TWidgetMainForm }
  TWidgetMainForm = class(TWidgetForm)
  private
    FThread: TInetThread;
    FMainMenu: HMENU;
    FAmungusID,
    FTitle: WideString;
    FWidgetURL: WideString;
    FInterval: Integer;
    FDragging: Boolean;
    FPrevious,
    FTracker: Integer;
    FSection: WideString;
    FChangeControl: TWidgetImageControl;
    FPreviousLabel: TWidgetLabel;
    FCloseLabel: TWidgetLabel;
    FAlwaysTop,
    FEnableTracker: Boolean;
    FInitDelay: Integer;
    FBusyControl: TWidgetImageControl;
    FOpacityMax: Integer;
    FEffect: Boolean;
    FShowHide: Boolean;
    FDialogHandle: HWND;
    FIgnoreMouse: Boolean;
    FPreventDragging: Boolean;
    FBackColor: Cardinal;
  protected
    procedure WndProc(var Message: TWidgetMessage); override;
    procedure WMTimer(var Message: TWidgetMessage); override;
    procedure WMDestroy(var Message: TWidgetMessage); override;
    procedure WMClose(var Message: TWidgetMessage); override;
    procedure WMCommand(var Message: TWidgetMessage); virtual;
    procedure WMWindowPosChanging(var Message: TWidgetMessage); override;
    procedure WMThreadDone(var Message: TWidgetMessage); virtual;
    procedure WMHideForm(var Message: TWidgetMessage); virtual;
    procedure WMShowForm(var Message: TWidgetMessage); virtual;
    procedure WMAlwaysTop(var Message: TWidgetMessage); virtual;
    procedure WMChangeLang(var Message: TWidgetMessage); virtual;
  public
    TrackerLabel,
    TitleLabel: TWidgetLabel;
    Background,
    Overlay: TWidgetImageControl;
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure CreateForm; override;
    procedure CreateControls;
    procedure DoMouseDown(Sender: TObject; Keys: Integer; X, Y: Integer);
    procedure DoCloseButtonClick(Sender: TObject; Keys: Integer; X, Y: Integer);
    procedure LoaderTimerExecute(Sender: TObject);
    procedure RefreshTimerExecute(Sender: TObject);
    procedure RefreshTracker;
    procedure DialogCloseButtonClick(Sender: TObject; Keys: Integer; X, Y: Integer);
    procedure RightButtonClick(Sender: TObject);
    procedure ClickAboutMenu(Sender: TObject);
    procedure ClickExitMenu(Sender: TObject);
    procedure ClickUpdateMenu(Sender: TObject);
    procedure ClickAlwaysTopMenu(Sender: TObject);
    procedure ClickHibernateMenu(Sender: TObject);
    procedure ClickShowHideMenu(Sender: TObject);
    procedure ClickOptionsMenu(Sender: TObject);
    procedure ClickDetailsMenu(Sender: TObject);
    procedure ClickDeleteMenu(Sender: TObject);
    procedure ControlHide(Control: TWidgetControl);
    procedure ControlShow(Control: TWidgetControl);
    procedure ShowForm;
    procedure HideForm;
    procedure ChangeAlwaysTop(const Value: Boolean);
    procedure ChangeRefresh(const Value: Integer);
    procedure ChangeShowHide(const Value: Boolean);
    procedure ChangeIgnoreMouse(const Value: Boolean);
    procedure ChangePreventDragging(const Value: Boolean);
    function FormatTracker(const Value: Integer): WideString;
    function FormatPrevious(const Value1, Value2: Integer): WideString;
    function FormatChangeImage(const Value1, Value2: Integer): WideString;
    function ProcessMessage(var Msg: TMsg): Boolean;
    procedure ProcessMessages;
    procedure ModifyLanguage;
    procedure ModifyMenuLanguage;
    procedure DeleteSelf;
    { Properties }
    property WidgetURL: WideString read FWidgetURL write FWidgetURL;
    property AmungusID: WideString read FAmungusID write FAmungusID;
    property Title: WideString read FTitle write FTitle;
    property Interval: Integer read FInterval write FInterval;
    property Section: WideString read FSection write FSection;
    property Tracker: Integer read FTracker write FTracker;
    property Previous: Integer read FPrevious write FPrevious;
    property AlwaysTop: Boolean read FAlwaysTop write FAlwaysTop;
    property IgnoreMouse: Boolean read FIgnoreMouse write FIgnoreMouse;
    property PreventDragging: Boolean read FPreventDragging write FPreventDragging;
    property InitDelay: Integer read FInitDelay write FInitDelay;
    property OpacityMax: Integer read FOpacityMax write FOpacityMax;
    property EnableTracker: Boolean read FEnableTracker write FEnableTracker;
    property Effect: Boolean read FEffect write FEffect;
    property DialogHandle: HWND read FDialogHandle write FDialogHandle;
    property BackColor: Cardinal read FBackColor write FBackColor;
  end;

  { TAboutForm }
  TAboutForm = class(TWidgetForm)
  private
    Background: TWidgetImageControl;
    TitleLabel,
    VersionLabel,
    CopyrightLabel,
    HomepageLabel: TWidgetLabel;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure PaintWindow; override;
    procedure CreateForm; override;
    procedure CreateControls;
    procedure ShowForm;
    procedure HideForm;
    procedure ControlHide(Control: TWidgetControl);
    procedure ControlShow(Control: TWidgetControl);
    procedure DoMouseDown(Sender: TObject; Keys: Integer; X, Y: Integer);
    procedure HomepageLabelClick(Sender: TObject; Keys: Integer; X, Y: Integer);
  end;

  { TWidgetImageControl }
  TWidgetImageControl = class(TWidgetControl)
  private
    FImage: TWidgetImage;
    FCached: TGPCachedBitmap;
    FFileName: string;
    procedure SetFileName(const Value: string);
    procedure AllocateImage;
    procedure ReleaseImage;
  protected
    procedure CreateParams(var Params: TCreateParamsW); override;
    procedure ChangeImageData(Data: TBitmapData; Color: Cardinal; Opacity: Byte);
    procedure ChangeImage(ABitmap: TGPBitmap; Color: Cardinal; Opacity: Byte);
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure PaintWindow; override;
    procedure CreateHandle; override;
    procedure ColorizeImage(const Color: TGPColor);
    procedure OpacityImage(const AImageOpacity: Byte);
    { Properties }
    property FileName: string read FFileName write SetFileName;
    property Image: TWidgetImage read FImage;
  end;

  { TWidgetLabel }
  TWidgetLabel = class(TWidgetControl)
  private
    FBorder: Boolean;
    FShadow: Boolean;
    FTransparent: Boolean;
  protected
    procedure CreateParams(var Params: TCreateParamsW); override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure PaintWindow; override;
    property Border: Boolean read FBorder write FBorder;
    property Shadow: Boolean read FShadow write FShadow;
    property Transparent: Boolean read FTransparent write FTransparent;
  end;
  
  { TFormList }
  TFormList = class(TObjectList)
  end;

  { TWidgetManager }
  TWidgetManager = class(TWinForm)
  private
    FFormList: TFormList;
    FIniFile: TWMemIniFile;
    FWidgetTray: TWidgetTray;
    FConfigFolder: WideString;
    FThread: TInetThread;
    FVersionThread: TInetThread;
    FMainMenu: HMENU;
    FMultiThread: Boolean;
    FDialogHandle: HWND;
    FLangsMenu: HMENU;
    FWidgetsMenu: HMENU;
    FFirstTime: Boolean;
    FAboutForm: TAboutForm;
    function GetCount: Integer;
    function GetItem(Index: Integer): TWidgetMainForm;
  protected
    procedure CreateParams(var Params: TCreateParamsW); override;
    procedure WndProc(var Message: TWidgetMessage); override;
    procedure WMDestroy(var Message: TWidgetMessage); override;
    procedure WMClose(var Message: TWidgetMessage); override;
    procedure WMTimer(var Message: TWidgetMessage); override;
    procedure WMThreadDone(var Message: TWidgetMessage);
    procedure WMVersionDone(var Message: TWidgetMessage);
    procedure WMCommand(var Message: TWidgetMessage); virtual;
    procedure WMDetails(var Message: TWidgetMessage); virtual;
    procedure WMDeleteWidget(var Message: TWidgetMessage); virtual;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure CreateForm; override;
    procedure CreateMenu;
    procedure UpdateTrayMenu;
    procedure UpdateLangsMenu;
    procedure UpdateWidgtesMenu;
    procedure ModifyLanguage;
    procedure ModifyMenuLanguage;
    procedure CreateTray;
    procedure LoaderTimerExecute(Sender: TObject);
    procedure Initialize;
    procedure TrayMouseUp(Sender: TObject; Keys: Integer; X, Y: Integer);
    procedure TrayDblClick(Sender: TObject);
    function ProcessMessage(var Msg: TMsg): Boolean;
    procedure ProcessMessages;
    procedure SaveChanges;
    procedure CheckTracker;
    procedure CheckVersion;
    procedure ClickAboutMenu(Sender: TObject);
    procedure ClickExitMenu(Sender: TObject);
    procedure ClickHideMenu(Sender: TObject);
    procedure ClickShowMenu(Sender: TObject);
    procedure ClickAddWidgetMenu(Sender: TObject);
    procedure ClickWidgetsMenu(Sender: TObject; const MenuIndex: Integer);
    procedure ClickLangsMenu(Sender: TObject; const MenuIndex: Integer);
    procedure RightButtonClick(Sender: TObject);
    procedure HideForms;
    procedure ShowForms;
    function Add(WidgetForm: TWidgetMainForm): Integer;
    function Delete(WidgetForm: TWidgetMainForm): Integer;
    function AddAmungus(const ASection, ATitle: WideString; const AInitDelay: Integer): Integer;
    function GetByHandle(const AHandle: HWND): TWidgetMainForm;
    function GetByAmungusId(const AmungusId: WideString): TWidgetMainForm;
    procedure DeleteAmungus(const AmungusId: WideString);
    procedure DeleteByHandle(const AHandle: HWND);
    property Count: Integer read GetCount;
    property FormList: TFormList read FFormList;
    property Items[Index: Integer]: TWidgetMainForm read GetItem;
    property MultiThread: Boolean read FMultiThread write FMultiThread;
    property DialogHandle: HWND read FDialogHandle write FDialogHandle;
  end;

  { TWidgetApplication }
  TWidgetApplication = class
  private
    FRunning: Boolean;
    FMutex: THandle;
    FTimeCaps: TTimeCaps;
    FTitle: WideString;
    function GetRunning: Boolean;
    function GetHandle: HWND;
  public
    constructor Create;
    destructor Destroy; override;
    procedure Initialize;
    procedure Finalize;
    procedure Run;
    procedure InitializeMutex;
    procedure FinalizeMutex;
    property Handle: HWND read GetHandle;
    property Running: Boolean read GetRunning;
    property Title: WideString read FTitle write FTitle;
  end;

  { TWidgetLanguage }
  TWidgetLanguage = class(TObject)
  private
    FIniFile: TWMemIniFile;
    FID: WideString;
    FName: WideString;
    function GetText(const Ident: Integer): WideString;
    procedure SetText(const Ident: Integer; const Value: WideString);
  public
    constructor Create(const AID: WideString; IniFile: TWMemIniFile);
    destructor Destroy; override;
    property ID: WideString read FID;
    property Name: WideString read FName;
    property Text[const Ident: Integer]: WideString read GetText write SetText; default;
  end;

  { TWidgetLanguages }
  TWidgetLanguages = class(TComponent)
  private
    FItems: TObjectList;
    FNames: TWStringList;
    FCurrent: TWidgetLanguage;
    function GetText(const Ident: Integer): WideString;
    procedure SetText(const Ident: Integer; const Value: WideString);
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure Initialize;
    procedure Add(const FileName: WideString);
    procedure Release;
    procedure Change(const ID: WideString);
    function Find(const ID: WideString): TWidgetLanguage;
    property Text[const Ident: Integer]: WideString read GetText write SetText; default;
  end;

var
  WidgetManager: TWidgetManager;
  WidgetApplication: TWidgetApplication = nil;
  WLang: TWidgetLanguages;

{ OpenInternet }
function OpenInternet: Boolean;

{ CloseInternet }
procedure CloseInternet;

implementation

uses
  Variants, DialogRes, SettingsDlg, AddWidgetDlg;

const
  WidgetVersion    = '1.50';
  WidgetAppName    = 'Amungus' + WidgetVersion;
  WidgetMutexName  = WidgetAppName + '_Widget_Manager_Mutex_Name';
  WidgetClassName  = WidgetAppName + '_Widget_Manager_Class_Name';
  WidgetWindowName = WidgetAppName + '_Widget_Manager_Window_Name';
  WidgetAppFolder  = '\Shenturk\Amungus';

const
  IDT_REFRESHTIMER  = 1001;
  IDT_LOADERTIMER   = 1002;

var
  FInternet: HINTERNET = nil;
  FCallbackProc: INTERNET_STATUS_CALLBACK = nil;

{ OpenInternet }
function OpenInternet: Boolean;
begin
  CloseInternet;
  FInternet := InternetOpen('Amungus Explorer 0.31',
    INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
  Result := FInternet <> nil;
  if Result and Assigned(FCallbackProc) then
    InternetSetStatusCallback(FInternet, FCallbackProc);
end;

{ CloseInternet }
procedure CloseInternet;
begin
  if FInternet <> nil then
    if InternetCloseHandle(FInternet) then
      FInternet := nil;
end;

{ GetTempFolderPath }
function GetTempFolderPath: WideString;
begin
  SetLength(Result, MAX_PATH);
  GetTempPathW(MAX_PATH, PWideChar(Result));
  Result := PWideChar(Result);
end;

{ GetSpecialFolderPath }
function GetSpecialFolderPath(nFolder: Integer): WideString;
begin
  SetLength(Result, MAX_PATH);
  if SHGetSpecialFolderPathW(GetDesktopWindow(), PWideChar(Result), nFolder, False) then
    Result := PWideChar(Result)
  else Result := '';
end;

{ GetUserAppDataPath }
function GetUserAppDataPath: WideString;
begin
  Result := GetSpecialFolderPath(CSIDL_APPDATA) + WidgetAppFolder;
end;

{ SetMenuText }
procedure SetMenuText(Menu: HMENU; const Index: Integer; const Text: WideString);
var
  mii: MENUITEMINFOW;
begin
  FillChar(mii, SizeOf(MENUITEMINFOW), 0);
  mii.cbSize := SizeOf(MENUITEMINFOW);
  mii.fMask := MIIM_STRING;
  mii.dwTypeData := PWideChar(Text);
  mii.cch := Length(Text);
  SetMenuItemInfoW(Menu, Index, False, mii);
end;

{ ParseVersionXML }
function ParseVersionXML(const strXML: WideString): string;
var
  xmlPage, Elem: OleVariant;
begin
  Result := '';
  xmlPage := CreateOleObject('Microsoft.XMLDOM');
  try
    if not VarIsClear(xmlPage) then
    begin
      if xmlPage.LoadXml(strXML) then
      begin
        // /data/version
        Elem := xmlPage.documentElement.selectSingleNode('/data/version');
        try
          if not VarIsClear(Elem) then
            Result := Elem.Text;
        finally
          Elem := Unassigned;
        end;
      end;
    end;
  finally
    xmlPage := Unassigned;
  end;
end;

{ WidgetThreadFunc }
function WidgetThreadFunc(Parameter: Pointer): Integer;
var
  Msg: TMsg;
  WidgetForm: TWidgetMainForm;
begin
  Result := -1;
  WidgetForm := TWidgetMainForm(Parameter);
  WidgetForm.HandleNeeded;
  if WidgetForm.Handle <> 0 then
  begin
    try
      InitCommonControls;
      // Call coinitialize on this thread
      if (CoInitFlags = -1) and (IsMultiThread) then
        CoInitFlags := COINIT_MULTITHREADED; // Required for multithreaded
      if Assigned(ComObj.CoInitializeEx) and (CoInitFlags <> -1) then
        ComObj.CoInitializeEx(nil, CoInitFlags)
      else CoInitialize(nil);
      WidgetForm.Visible := True;
      WidgetForm.ShowForm;
      WidgetForm.Update;
      Result := 0;
      while GetMessage(Msg, 0, 0, 0) do
      begin
        TranslateMessage(Msg);
        DispatchMessage(Msg);
      end;
      CoUninitialize;
    finally
      //OutputDebugString('End of Message Loop');
    end;
  end;
  EndThread(0);
end;

{ TWidgetMainForm }

procedure TWidgetMainForm.ChangeAlwaysTop(const Value: Boolean);
const
  CTopMost: array[Boolean] of Cardinal= (HWND_NOTOPMOST, HWND_TOPMOST);
begin
  FAlwaysTop := Value;
  SetWindowPos(Self.Handle, CTopMost[Value], 0, 0, 0, 0,
    SWP_NOMOVE or SWP_NOSIZE or SWP_FRAMECHANGED);
  SetForegroundWindow(Self.Handle);
  SetActiveWindow(Self.Handle);
  Self.Update;
end;

procedure TWidgetMainForm.ChangeIgnoreMouse(const Value: Boolean);
begin
  FIgnoreMouse := Value;
  if FIgnoreMouse then
  begin
    if Self.ExStyle and WS_EX_TRANSPARENT = 0 then
      Self.ExStyle := Self.ExStyle or WS_EX_TRANSPARENT;
  end
  else begin
    if Self.ExStyle and WS_EX_TRANSPARENT <> 0 then
      Self.ExStyle := Self.ExStyle and not WS_EX_TRANSPARENT;
  end;
end;

procedure TWidgetMainForm.ChangePreventDragging(const Value: Boolean);
begin
  FPreventDragging := Value;
end;

procedure TWidgetMainForm.ChangeRefresh(const Value: Integer);
begin
  FInterval := Value;
end;

procedure TWidgetMainForm.ChangeShowHide(const Value: Boolean);
begin
  if Value then ShowForm
  else HideForm;
end;

procedure TWidgetMainForm.ClickAboutMenu(Sender: TObject);
var
  S: WideString;
begin
  S := WLang[MC_ABOUT];
  if S[1] = '&' then Delete(S, 1, 1);
  MessageBoxW(Self.Handle,
    'Amung.us Desktop Widget v1.50'#13#10#13#10 +
    'Copyright (c) 2008 Shenturk.com',
    PWideChar(S),
    MB_OK);
end;

procedure TWidgetMainForm.ClickAlwaysTopMenu(Sender: TObject);
begin
  FAlwaysTop := not FAlwaysTop;
  ChangeAlwaysTop(FAlwaysTop);
end;

procedure TWidgetMainForm.ClickDeleteMenu(Sender: TObject);
begin
  DeleteSelf;
end;

procedure TWidgetMainForm.ClickDetailsMenu(Sender: TObject);
begin
  SendMessageW(WidgetManager.Handle, WM_DETAILS, 0, Self.Handle);
end;

procedure TWidgetMainForm.ClickExitMenu(Sender: TObject);
begin
  PostMessageW(WidgetManager.Handle, WM_CLOSE, 0, 0);
end;

procedure TWidgetMainForm.ClickHibernateMenu(Sender: TObject);
begin
  FIgnoreMouse := not FIgnoreMouse;
  ChangeIgnoreMouse(FIgnoreMouse);
end;

procedure TWidgetMainForm.ClickOptionsMenu(Sender: TObject);
begin
  if FDialogHandle = 0 then
    DialogBoxParamW(MainInstance, MakeIntResourceW(IDD_SETTINGS_DLG),
      Self.Handle, @SettingsDlgProc, Integer(Self))
  else begin
    SetActiveWindow(FDialogHandle);
    SetForegroundWindow(FDialogHandle);
  end;
end;

procedure TWidgetMainForm.ClickShowHideMenu(Sender: TObject);
begin
  FShowHide := not FShowHide;
  ChangeShowHide(FShowHide);
end;

procedure TWidgetMainForm.ClickUpdateMenu(Sender: TObject);
begin
  RefreshTracker;
end;

procedure TWidgetMainForm.ControlHide(Control: TWidgetControl);
const
  Step = 8;
  Wait = 4;
begin
  while Control.Opacity > 0 do
  begin
    if Control.Opacity - Step <= 0 then
    begin
      Control.Opacity := 0;
      Self.Update;
      Break;
    end;
    Control.Opacity := Control.Opacity - Step;
    Self.Update;
    Sleep(Wait);
  end;
  Control.Hide;
end;

procedure TWidgetMainForm.ControlShow(Control: TWidgetControl);
begin
  Control.Show;
  Control.Opacity := 255;
  Self.Update;
end;

constructor TWidgetMainForm.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  Width := 79;
  Height := 74;
  Left := Desktop.DesktopWidth - Width;
  Top := Desktop.WorkAreaHeight - Height;
  OnMouseDown := DoMouseDown;
  FInterval := 20000;
  FOpacityMax := $FF;
  FShowHide := True;
  with Canvas do begin
    Pen.Color := $FFFFFFFF;
    Brush.Color := $40000000;
  end;
end;

procedure TWidgetMainForm.CreateControls;
begin

  Background := TWidgetImageControl.Create(Self);
  with Background do
  begin
    Parent := Self;
    OnMouseDown := DoMouseDown;
    FileName := 'SHADOW.PNG';
    Width := 79;
    Height := 74;
    Left := 0;
    Top := 0;
    ColorizeImage(ColorRefToARGB(FBackColor));
    Opacity := 255;
    Visible := True;
  end;

  TrackerLabel := TWidgetLabel.Create(Self);
  with TrackerLabel do
  begin
    Parent := Self;
    Width := 79;
    Height := 29;
    Left := 0;
    Top := Self.Height - Height - 20;
    Enabled := False;
    Cursor := LoadCursor(0, IDC_HAND);
    with Canvas do begin
      Pen.Color := $FFFFFFFF;
      Font.Format.Alignment := StringAlignmentCenter;
      Font.Format.LineAlignment := StringAlignmentCenter;
      Font.Name := 'Trebuchet MS';
      Font.Size := 18;
      //Font.Style := FontStyleBold;
      Font.Color := $FFFFFFFF;
    end;
    Caption := FormatTracker(FTracker);
    Enabled := False;
    Visible := True;
  end;

  FPreviousLabel := TWidgetLabel.Create(Self);
  with FPreviousLabel do
  begin
    Parent := Self;
    Width := 70;
    Height := 14;
    Left := 8;
    Top := Self.Height - Height - 8;
    Enabled := False;
    Cursor := LoadCursor(0, IDC_HAND);
    with Canvas do begin
      Pen.Color := $FFFFFFFF;
      Font.Format.Alignment := StringAlignmentNear;
      Font.Format.LineAlignment := StringAlignmentCenter;
      Font.Name := 'Trebuchet MS';//'Tahoma';//
      Font.Size := 9;
      //Font.Style := FontStyleBold;
      Font.Color := $FFA0A0A0;
    end;
    Caption := FormatPrevious(FPrevious, FTracker);
    Enabled := False;
    Visible := True;
  end;

  FChangeControl := TWidgetImageControl.Create(Self);
  with FChangeControl do begin
    Parent := Self;
    Width := 12;
    Height := 12;
    Left := Self.Width - Width - 4;
    Top := 23;
    FileName := FormatChangeImage(FPrevious, FTracker);
    Enabled := False;
    Visible := True;
  end;

  Overlay := TWidgetImageControl.Create(Self);
  with Overlay do
  begin
    Parent := Self;
    OnMouseDown := DoMouseDown;
    FileName := 'OVERLAY.PNG';
    Width := 79;
    Height := 74;
    Left := 0;
    Top := 0;
    Enabled := False;
    Visible := True;
  end;

  TitleLabel := TWidgetLabel.Create(Self);
  with TitleLabel do
  begin
    Parent := Self;
    Left := 0;
    Top := 0;
    Width := Self.Width;
    Height := 18;
    with Canvas do begin
      Font.Format.Alignment := StringAlignmentCenter;
      Font.Format.LineAlignment := StringAlignmentCenter;
      Font.Name := 'Trebuchet MS';//'Arial Unicode MS';//
      Font.Size := 8;
      Font.Color := $FFFFFFFF;
    end;
    Caption := FTitle;
    Enabled := False;
    Visible := True;
  end;

  FCloseLabel := TWidgetLabel.Create(Self);
  with FCloseLabel do
  begin
    Parent := Self;
    OnClick := DoCloseButtonClick;
    Width := 12;
    Height := 12;
    Left := Self.Width - Width - 5;
    Top := 4;
    Cursor := LoadCursor(0, IDC_HAND);
    with Canvas do begin
      Font.Format.Alignment := StringAlignmentCenter;
      Font.Format.LineAlignment := StringAlignmentCenter;
      Font.Name := 'Wingdings 2';
      Font.Size := 13;
      Font.Color := $FFFF8000;
      Font.Style := FontStyleBold;
    end;
    Caption := #$004F;
  end;

  FBusyControl := TWidgetImageControl.Create(Self);
  with FBusyControl do begin
    Parent := Self;
    FileName := CStateImages[False];
    Width := 6;
    Height := 6;
    Left := Self.Width - 2 * Width;
    Top := Self.Height - 2 * Height - 1;
    Enabled := False;
    //Border := True;
    Visible := True;
  end;

end;

procedure TWidgetMainForm.CreateForm;
begin
  inherited CreateForm;
  FMainMenu := LoadMenuW(SysInit.HInstance, MakeIntResource(IDM_MAINMENU));
  ModifyMenuLanguage;
  ChangeAlwaysTop(FAlwaysTop);
  ChangeIgnoreMouse(FIgnoreMouse);
  ChangePreventDragging(FPreventDragging);
  ChangeRefresh(FInterval);
  CreateControls;
  SetTimer(Self.Handle, IDT_LOADERTIMER, FInitDelay, nil);
end;

procedure TWidgetMainForm.DeleteSelf;
begin
  if MessageBoxW(Self.Handle,
    PWideChar(WLang[IDS_TEXT_1006]),
    PWideChar(WLang[IDS_TEXT_1003]), MB_YESNO or MB_ICONWARNING) = IDYES then
    PostMessageW(WidgetManager.Handle, WM_DELETEWIDGET, 0, Self.Handle);
end;

destructor TWidgetMainForm.Destroy;
begin
  inherited Destroy;
end;

procedure TWidgetMainForm.DialogCloseButtonClick(Sender: TObject; Keys, X,
  Y: Integer);
begin
  Self.Opacity := FOpacityMax;
  Self.UpdateForm;
end;

procedure TWidgetMainForm.DoCloseButtonClick(Sender: TObject; Keys, X,
  Y: Integer);
begin
  ClickExitMenu(Sender);
end;

procedure TWidgetMainForm.DoMouseDown(Sender: TObject; Keys, X, Y: Integer);
var
  AcceptDragging: Boolean;
begin
  AcceptDragging := (Keys and MK_LBUTTON <> 0);
  if PreventDragging then
    AcceptDragging := (Keys and MK_CONTROL <> 0);
  if Keys and MK_LBUTTON <> 0 then
  begin
    if AcceptDragging then
    begin
      FDragging := True;
      ReleaseCapture;
      SendMessageW(Self.Handle, WM_SYSCOMMAND, SC_DRAGMOVE, 0);
      FDragging := False;
    end;
  end
  else if Keys and MK_RBUTTON <> 0 then RightButtonClick(Self);
end;

function TWidgetMainForm.FormatChangeImage(const Value1,
  Value2: Integer): WideString;
begin
  if Value1 > Value2 then Result := CChangeImages[-1]
  else if Value1 < Value2 then Result := CChangeImages[1]
  else Result := CChangeImages[0];
end;

function TWidgetMainForm.FormatPrevious(const Value1,
  Value2: Integer): WideString;
begin
  if Value1 < 0 then Result := '?'
  else Result := IntToStr(Value1);
end;

function TWidgetMainForm.FormatTracker(const Value: Integer): WideString;
begin
  if Value < 0 then Result := '?'
  else Result := IntToStr(Value);
end;

procedure TWidgetMainForm.HideForm;
const
  Step = 8;
  Wait = 4;
begin

  FShowHide := False;
  CheckMenuItem(FMainMenu, MC_HIDE, MF_BYCOMMAND or CChecks[not FShowHide]);

  while Self.Opacity > 0 do
  begin
    if Self.Opacity - Step <= 0 then
    begin
      Self.Opacity := 0;
      Self.UpdateForm;
      Break;
    end;
    Self.Opacity := Self.Opacity - Step;
    Self.UpdateForm;
    Self.ProcessMessages;
    Sleep(Wait);
  end;

  Self.Hide;
end;

procedure TWidgetMainForm.LoaderTimerExecute(Sender: TObject);
begin
  KillTimer(Self.Handle, IDT_LOADERTIMER);
  if FEnableTracker then
  begin
    if FInterval >= INTERVAL_MIN then
      SetTimer(Self.Handle, IDT_REFRESHTIMER, 100, nil);
  end;
  
end;

procedure TWidgetMainForm.ModifyLanguage;
begin
  ModifyMenuLanguage;
  Self.Update;
end;

procedure TWidgetMainForm.ModifyMenuLanguage;
var
  Menu: HMENU;
begin
  Menu := GetSubMenu(FMainMenu, 0);
  SetMenuText(Menu, MC_OPTIONS, WLang[MC_OPTIONS]);
  SetMenuText(Menu, MC_REFRESH, WLang[MC_REFRESH]);
  SetMenuText(Menu, MC_HIDE, WLang[MC_HIDE]);
  SetMenuText(Menu, MC_DELETE, WLang[MC_DELETE]);
  SetMenuText(Menu, MC_DETAILS, WLang[MC_DETAILS]);
end;

function TWidgetMainForm.ProcessMessage(var Msg: TMsg): Boolean;
begin
  Result := False;
  if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then
  begin
    Result := True;
    if Msg.Message <> WM_QUIT then
    begin
      TranslateMessage(Msg);
      DispatchMessage(Msg);
    end;
    //else FTerminated := True;
  end
  //else WaitMessage; // WaitMessage olmazsa islemci kullanimi %100 e vurur.
end;

procedure TWidgetMainForm.ProcessMessages;
var
  Msg: TMsg;
begin
  while ProcessMessage(Msg) do {loop};
end;

procedure TWidgetMainForm.RefreshTimerExecute(Sender: TObject);
begin
  if FEnableTracker then
  begin
    KillTimer(Self.Handle, IDT_REFRESHTIMER);
    RefreshTracker;
    if FInterval >= INTERVAL_MIN then
      SetTimer(Self.Handle, IDT_REFRESHTIMER, FInterval, nil);
  end;
end;

procedure TWidgetMainForm.RefreshTracker;
begin
  if not Assigned(FThread) then
  begin
    FThread := TInetThread.Create(Self.Handle, WM_THREADDONE, FInternet);
    try
      with FThread.Request do
      begin
        Host := 'whos.amung.us';
        {FWidgetURL := '/ajax/ffcount.php?k=' + FAmungusID;} { v1.0 }
        FWidgetURL := '/sitecount/' + FAmungusID; { v1.50 }
        URL := FWidgetURL;
      end;
      FThread.Resume;
      FBusyControl.FileName := CStateImages[True];
    except
      FreeAndNil(FThread);
      FBusyControl.FileName := CStateImages[False];
    end;
    Self.Update;
  end;
end;

procedure TWidgetMainForm.RightButtonClick(Sender: TObject);
var
  P: TPoint;
begin
  if FMainMenu <> 0 then
  begin
    GetCursorPos(P);
    TrackPopupMenuEx(GetSubMenu(FMainMenu, 0),
      TPM_LEFTALIGN or TPM_LEFTBUTTON or TPM_VERTICAL,
      P.x, P.y, Self.Handle, nil);
  end;
end;

procedure TWidgetMainForm.ShowForm;
const
  Step = 8;
  Wait = 4;
begin

  Self.Show;

  SetForegroundWindow(Self.Handle);
  SetActiveWindow(Self.Handle);
  Self.Update;

  FShowHide := True;
  CheckMenuItem(FMainMenu, MC_HIDE, MF_BYCOMMAND or CChecks[not FShowHide]);

  while Self.Opacity < FOpacityMax do
  begin
    if Self.Opacity + Step >= FOpacityMax then
    begin
      Self.Opacity := FOpacityMax;
      Self.UpdateForm;
      Break;
    end;
    Self.Opacity := Self.Opacity + Step;
    Self.UpdateForm;
    Self.ProcessMessages;
    Sleep(Wait);
  end;

end;

procedure TWidgetMainForm.WMAlwaysTop(var Message: TWidgetMessage);
begin
  ClickAlwaysTopMenu(Self);
end;

procedure TWidgetMainForm.WMChangeLang(var Message: TWidgetMessage);
begin
  ModifyLanguage;
  if IsWindow(Self.FDialogHandle) then
    SendMessageW(Self.FDialogHandle, WM_CHANGELANG, 0, 0);
end;

procedure TWidgetMainForm.WMClose(var Message: TWidgetMessage);
begin
  if IsWindow(FDialogHandle) then
    SendMessageW(FDialogHandle, WM_CLOSE, 0, 0);
  HideForm;
  inherited WMClose(Message);
end;

procedure TWidgetMainForm.WMCommand(var Message: TWidgetMessage);
begin
  with Message do
    if HIWORD(wParam) = 0 then // from Menu
    begin
      case LOWORD(wParam) of
        MC_ABOUT: ClickAboutMenu(Self);
        MC_EXIT: ClickExitMenu(Self);
        MC_REFRESH: ClickUpdateMenu(Self);
        MC_DELETE: ClickDeleteMenu(Self);
        MC_DETAILS: ClickDetailsMenu(Self);
        MC_HIDE: ClickShowHideMenu(Self);
        MC_OPTIONS: ClickOptionsMenu(Self);
      end;
    end;
end;

procedure TWidgetMainForm.WMDestroy(var Message: TWidgetMessage);
begin
  KillTimer(Self.Handle, IDT_LOADERTIMER);
  KillTimer(Self.Handle, IDT_REFRESHTIMER);
  if Assigned(FThread) then
  begin
    if not FThread.Terminated then FThread.WaitFor;
    FreeAndNil(FThread);
  end;
  if FMainMenu <> 0 then DestroyMenu(FMainMenu);
  inherited WMDestroy(Message);
  if WidgetManager.MultiThread then PostQuitMessage(0);
end;

procedure TWidgetMainForm.WMHideForm(var Message: TWidgetMessage);
begin
  Self.HideForm;
end;

procedure TWidgetMainForm.WMShowForm(var Message: TWidgetMessage);
begin
  Self.ShowForm;
end;

procedure TWidgetMainForm.WMThreadDone(var Message: TWidgetMessage);
begin
  if Assigned(FThread) then
  begin
    with FThread.Request do
    begin
      FPrevious := FTracker;
      FTracker := StrToIntDef(Trim(Response.Content), -1);
      TrackerLabel.Caption := FormatTracker(FTracker);
      FPreviousLabel.Caption := FormatPrevious(FPrevious, FTracker);
      FChangeControl.FileName := FormatChangeImage(FPrevious, FTracker);
      FBusyControl.FileName := CStateImages[False];
    end;
    FreeAndNil(FThread);
  end;
  Self.Update;
end;

procedure TWidgetMainForm.WMTimer(var Message: TWidgetMessage);
begin
  case Message.WParam of
    IDT_REFRESHTIMER: RefreshTimerExecute(Self);
    IDT_LOADERTIMER : LoaderTimerExecute(Self);
  end;
end;

procedure TWidgetMainForm.WMWindowPosChanging(var Message: TWidgetMessage);
const
  SNAP_SIZE = 8;
var
  WP: PWINDOWPOS;
  R, R1, R2: TRect;
  I: Integer;
  Item: TWidgetMainForm;
begin

  inherited WMWindowPosChanging(Message);

  WP := PWINDOWPOS(Message.LParam);

  for I := 0 to WidgetManager.Count - 1 do
  begin
    Item := WidgetManager.Items[I];
    if (Item <> Self) and (Item.Visible) then
    begin

      R1 := Item.WindowRect;
      
      R.Bottom := R1.Top - (WP^.y + Self.Height);
      if (R.Bottom > -SNAP_SIZE) and (R.Bottom < SNAP_SIZE) then
        WP^.y := R1.Top - Self.Height;

      R.Bottom := R1.Bottom - (WP^.y + Self.Height);
      if (R.Bottom > -SNAP_SIZE) and (R.Bottom < SNAP_SIZE) then
        WP^.y := R1.Bottom - Self.Height;

      R.Top := WP^.y - R1.Bottom;
      if (R.Top > -SNAP_SIZE) and (R.Top < SNAP_SIZE) then
        WP^.y := R1.Bottom;

      R.Top := WP^.y - R1.Top;
      if (R.Top > -SNAP_SIZE) and (R.Top < SNAP_SIZE) then
        WP^.y := R1.Top;

      R.Right := R1.Left - (WP^.x + Self.Width);
      if (R.Right > -SNAP_SIZE) and (R.Right < SNAP_SIZE) then
        WP^.x := R1.Left - Self.Width;

      R.Right := R1.Right - (WP^.x + Self.Width);
      if (R.Right > -SNAP_SIZE) and (R.Right < SNAP_SIZE) then
        WP^.x := R1.Right - Self.Width;

      R.Left := WP^.x - R1.Right;
      if (R.Left > -SNAP_SIZE) and (R.Left < SNAP_SIZE) then
        WP^.x := R1.Right;

      R.Left := WP^.x - R1.Left;
      if (R.Left > -SNAP_SIZE) and (R.Left < SNAP_SIZE) then
        WP^.x := R1.Left

    end;
  end;

  R2 := Desktop.WorkAreaRect;

  R.Bottom := R2.Bottom - (WP^.y + Self.Height);
  if (R.Bottom > -SNAP_SIZE) and (R.Bottom < SNAP_SIZE) then
    WP^.y := R2.Bottom - Self.Height;

  R.Top := WP^.y - R2.Top;
  if (R.Top > -SNAP_SIZE) and (R.Top < SNAP_SIZE) then
    WP^.y := R2.Top;

  R.Right := R2.Right - (WP^.x + Self.Width);
  if (R.Right > -SNAP_SIZE) and (R.Right < SNAP_SIZE) then
    WP^.x := R2.Right - Self.Width;

  R.Left := WP^.x - R2.Left;
  if (R.Left > -SNAP_SIZE) and (R.Left < SNAP_SIZE) then
    WP^.x := R2.Left;

end;

procedure TWidgetMainForm.WndProc(var Message: TWidgetMessage);
begin
  case Message.Msg of
    WM_TIMER: WMTimer(Message);
    WM_THREADDONE: WMThreadDone(Message);
    WM_COMMAND: WMCommand(Message);
    WM_HIDEFORM: WMHideForm(Message);
    WM_SHOWFORM: WMShowForm(Message);
    WM_ALWAYSTOP: WMAlwaysTop(Message);
    WM_CHANGELANG: WMChangeLang(Message);
  else
    inherited WndProc(Message);
  end;
end;

{ TWidgetImageControl }

procedure TWidgetImageControl.AllocateImage;
begin
  {
  if FileExists(FFileName) then
    FImage := TWidgetImage.Create(FFileName)
  else }
    FImage := TWidgetImage.Create(FFileName, wifResource);
    FCached := TGPCachedBitmap.Create(FImage.Handle, Canvas.Graphics);
end;

procedure TWidgetImageControl.ChangeImage(ABitmap: TGPBitmap;
  Color: Cardinal; Opacity: Byte);
var
  Data: TBitmapData;
  R: TGPRect;
begin
  if not IsAlphaPixelFormat(ABitmap.GetPixelFormat) then Exit;
  R := MakeRect(Rect(0, 0, ABitmap.GetWidth, ABitmap.GetHeight));
  ABitmap.LockBits(R, ImageLockModeRead or ImageLockModeWrite, PixelFormat32bppARGB, Data);
  try
    ChangeImageData(Data, Color, Opacity);
  finally
    ABitmap.UnlockBits(Data);
  end;
end;

procedure TWidgetImageControl.ChangeImageData(Data: TBitmapData;
  Color: Cardinal; Opacity: Byte);
var
  X, Y: Cardinal;
  Pixel: Widgets.PARGB;
  R, G, B: Byte;
begin
  R := GetRValue(Color);
  G := GetGValue(Color);
  B := GetBValue(Color);
  for Y := 0 to Data.Height - 1 do
  begin
    Pixel := Widgets.PARGB(Cardinal(Data.Scan0) + Data.Width * 4 * Y);
    for X := 0 to Data.Width - 1 do
    begin
      {
      Pixel^.R := Pixel^.R * R shr $07;
      Pixel^.G := Pixel^.G * G shr $07;
      Pixel^.B := Pixel^.B * B shr $07;
      }
      Pixel^.R := R;
      Pixel^.G := G;
      Pixel^.B := B;
      //Pixel^.A := Pixel^.A * Opacity shr $08;
      Inc(Pixel);
    end;
  end;
end;

procedure TWidgetImageControl.ColorizeImage(const Color: TGPColor);
begin
  if Assigned(FImage) then
    ChangeImage(FImage.Handle, Color, $FF);
end;

constructor TWidgetImageControl.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
end;

procedure TWidgetImageControl.CreateHandle;
begin
  inherited CreateHandle;
end;

procedure TWidgetImageControl.CreateParams(var Params: TCreateParamsW);
begin
  inherited CreateParams(Params);
  CreateSubClass(Params, 'STATIC');
  with Params do Style := Style or SS_LEFT or SS_NOPREFIX or SS_NOTIFY;
end;

destructor TWidgetImageControl.Destroy;
begin
  ReleaseImage;
  inherited Destroy;
end;

procedure TWidgetImageControl.OpacityImage(const AImageOpacity: Byte);
begin
  {
  if Assigned(FImage) then
    FImage.OpacityImage(AImageOpacity);
  }
end;

procedure TWidgetImageControl.PaintWindow;
{
var
  Attr: TGPImageAttributes;
  ColorMap: TColorMap;
}
begin
  inherited PaintWindow;
  with Canvas.Graphics do
  begin
    if Visible and Assigned(FImage) then
    begin
      {
      if Assigned(FCached) then; DrawCachedBitmap(FCached, 0, 0);
      }
      {
      Attr := TGPImageAttributes.Create;
      try
        ColorMap.oldColor := MakeColor(255, 128, 128, 128);
        ColorMap.newColor := MakeColor(128, 255, 255, 0);
        Attr.SetRemapTable(1, @ColorMap, ColorAdjustTypeBitmap);
        DrawImage(FImage.Handle,
          MakeRect(0, 0, Self.Width, Self.Height),
          0, 0, Self.Width, Self.Height,
          UnitPixel,
          Attr);
      finally
        Attr.Free;
      end;
      }
      DrawImage(FImage.Handle, 0, 0, Self.Width, Self.Height);
      {
      DrawImage(FImage.Handle, 0, 0, Self.Width, Self.Height);
      DrawImage(FImage.Handle, 0, 0, Self.Width, Self.Height);
      DrawImage(FImage.Handle, 0, 0, Self.Width, Self.Height);
      DrawImage(FImage.Handle, 0, 0, Self.Width, Self.Height);
      }
    end;
  end;
end;

procedure TWidgetImageControl.ReleaseImage;
begin
  if Assigned(FCached) then FreeAndNil(FCached);
  if Assigned(FImage) then FreeAndNil(FImage);
end;

procedure TWidgetImageControl.SetFileName(const Value: string);
begin
  ReleaseImage;
  FFileName := Value;
  AllocateImage;
end;

{ TWidgetLabel }

constructor TWidgetLabel.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FShadow := True;
  FTransparent := True;
end;

procedure TWidgetLabel.CreateParams(var Params: TCreateParamsW);
begin
  inherited CreateParams(Params);
  CreateSubClass(Params, 'STATIC');
  with Params do Style := Style or SS_LEFT or SS_NOPREFIX or SS_NOTIFY;
end;

destructor TWidgetLabel.Destroy;
begin
  inherited Destroy;
end;

procedure TWidgetLabel.PaintWindow;
var
  R: TRect;
  SaveColor: TGPColor;
begin
  inherited PaintWindow;
  with Canvas do
  begin
    R := ClientRect;
    if not FTransparent then FillRectangle(R);
    if FShadow then
    begin
      OffsetRect(R, 1, 1);
      SaveColor := Font.Color;
      Font.Color := Font.Color and $40000000 or $0;
      DrawString(Caption, R);
      Font.Color := SaveColor;
      OffsetRect(R, -1, -1);
    end;
    DrawString(Caption, R);
    if FBorder then
    begin
      InflateRect(R, -1, -1);
      OffsetRect(R, 1, 1);
      DrawRectangle(R);
    end;
  end;
end;

{ TWidgetManager }

function TWidgetManager.Add(WidgetForm: TWidgetMainForm): Integer;
begin
  Result := -1;
  if FFormList.IndexOf(WidgetForm) < 0 then
    Result := FFormList.Add(WidgetForm);
end;

function TWidgetManager.AddAmungus(const ASection, ATitle: WideString;
  const AInitDelay: Integer): Integer;
var
  WidgetForm: TWidgetMainForm;
  Thread: THandle;
  dwThreadId: DWORD;
begin
  Result := -1;
  WidgetForm := TWidgetMainForm.Create(Self);
  with WidgetForm do
  begin
    Name := 'WidgetMainForm' + ASection;
    if Self.FMultiThread then
      ParentWindow := GetDesktopWindow() { Must be Desktop }
    else Parent := Self;
    Left := FIniFile.ReadInteger(ASection, 'Left', Desktop.WorkAreaRect.Right - 79);
    Top := FIniFile.ReadInteger(ASection, 'Top', Desktop.WorkAreaRect.Bottom - 74);
    Opacity := 0;
    Section := ASection;
    Interval := FIniFile.ReadInteger(ASection, 'Interval', 15000);
    AmungusID := ASection;
    Title := ATitle;
    WidgetURL := '/sitecount/' + ASection; { v1.50 }
    Tracker := FIniFile.ReadInteger(ASection, 'Tracker', -1);
    Previous := FIniFile.ReadInteger(ASection, 'Previous', -1);
    AlwaysTop := FIniFile.ReadBool(ASection, 'AlwaysTop', True);
    InitDelay := AInitDelay;
    OpacityMax := FIniFile.ReadInteger(ASection, 'Opacity', 255);
    EnableTracker := FIniFile.ReadBool(ASection, 'Enable', True);
    IgnoreMouse := FIniFile.ReadBool(ASection, 'IgnoreMouse', False);
    PreventDragging := FIniFile.ReadBool(ASection, 'PreventDragging', False);
    BackColor := FIniFile.ReadInteger(Section, 'BackColor', $000000);
    if Self.FMultiThread then
    begin
      Thread := BeginThread(nil, 0, WidgetThreadFunc, WidgetForm, CREATE_SUSPENDED, dwThreadId);
      if Thread <> 0 then begin
        Result := Self.Add(WidgetForm);
        ResumeThread(Thread);
      end;
      Sleep(20);
    end
    else begin
      Visible := True;
      ShowForm;
      Result := Self.Add(WidgetForm);
    end;
  end;

end;

procedure TWidgetManager.CheckTracker;
begin
  if not Assigned(FThread) then
  begin
    FThread := TInetThread.Create(Self.Handle, WM_THREADDONE, FInternet);
    try
      with FThread.Request do
      begin
        Host := 'whos.amung.us';
        URL := '/widget/75t8h6jqah6v.png';
      end;
      FThread.Resume;
    except
      FreeAndNil(FThread);
    end;
  end;
end;

procedure TWidgetManager.CheckVersion;
begin
  if not Assigned(FVersionThread) then
  begin
    FVersionThread := TInetThread.Create(Self.Handle, WM_VERSIONDONE, FInternet);
    try
      with FVersionThread.Request do
      begin
        Host := 'www.shenturk.com';
        URL := '/amungus.xml';
      end;
      FVersionThread.Resume;
    except
      FreeAndNil(FVersionThread);
    end;
  end;
end;

procedure TWidgetManager.ClickAboutMenu(Sender: TObject);
begin
  if not Assigned(FAboutForm) then
  begin
    FAboutForm := TAboutForm.Create(Self);
    FAboutForm.Parent := Self;
    FAboutForm.Opacity := 0;
  end;
  FAboutForm.ShowForm;
  FAboutForm.Update;
end;

procedure TWidgetManager.ClickAddWidgetMenu(Sender: TObject);
begin
  if FDialogHandle = 0 then
    DialogBoxParamW(MainInstance, MakeIntResourceW(IDD_ADDWIDGET_DLG),
      Self.Handle, @AddWidgetDlgProc, Integer(Self))
  else begin
    SetActiveWindow(FDialogHandle);
    SetForegroundWindow(FDialogHandle);
  end;
end;

procedure TWidgetManager.ClickExitMenu(Sender: TObject);
begin
  SendMessageW(Handle, WM_CLOSE, 0, 0);
end;

procedure TWidgetManager.ClickHideMenu(Sender: TObject);
begin
  HideForms;
end;

procedure TWidgetManager.ClickLangsMenu(Sender: TObject;
  const MenuIndex: Integer);
var
  Index: Integer;
  Language: TWidgetLanguage;
  I: Integer;
  Widget: TWidgetMainForm;
begin
  if MenuIndex >= MC_LANGUAGE_START then
  begin
    Index := MenuIndex - MC_LANGUAGE_START;
    if (Index >= 0) and (Index < WLang.FItems.Count) then
    begin
      Language := WLang.FItems[Index] as TWidgetLanguage;
      WLang.Change(Language.ID);

      ModifyLanguage;
      if IsWindow(Self.FDialogHandle) then
        SendMessageW(Self.FDialogHandle, WM_CHANGELANG, 0, 0);

      for I := 0 to Self.Count - 1 do
      begin
        Widget := Self.GetItem(I);
        PostMessageW(Widget.Handle, WM_CHANGELANG, 0, 0);
      end;
    end;
  end;
end;

procedure TWidgetManager.ClickShowMenu(Sender: TObject);
begin
  ShowForms;
end;

procedure TWidgetManager.ClickWidgetsMenu(Sender: TObject; const MenuIndex: Integer);
var
  Index: Integer;
  Widget: TWidgetMainForm;
begin
  if MenuIndex >= MC_WIDGETS_START then
  begin
    Index := MenuIndex - MC_WIDGETS_START;
    if Index >= 0 then
    begin
      Widget := Self.GetItem(Index);
      PostMessageW(Widget.Handle, WM_COMMAND, MC_OPTIONS, 0);
    end;
  end;
end;

constructor TWidgetManager.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FFormList := TFormList.Create(False);
  FConfigFolder := GetUserAppDataPath();
  ForceDirectories(FConfigFolder);
  FMultiThread := True;
end;

procedure TWidgetManager.CreateForm;
begin
  inherited CreateForm;
  Caption := WidgetWindowName;
  CreateMenu;
  CreateTray;
  SetTimer(Self.Handle, IDT_LOADERTIMER, 500, nil);
end;

procedure TWidgetManager.CreateMenu;
begin
  if FMainMenu <> 0 then DestroyMenu(FMainMenu);
  FMainMenu := LoadMenuW(SysInit.HInstance, MakeIntResource(IDM_TRAYMENU));
  UpdateTrayMenu;
  ModifyLanguage;
end;

procedure TWidgetManager.CreateParams(var Params: TCreateParamsW);
begin
  inherited CreateParams(Params);
  CreateSubClass(Params, WidgetClassName);
end;

procedure TWidgetManager.CreateTray;
begin
  FWidgetTray := TWidgetTray.Create(Self);
  with FWidgetTray do
  begin
    ParentWindow := GetDesktopWindow();
    Icon := LoadIcon(MainInstance, MakeIntResource(101));
    OnDblClick := TrayDblClick;
    OnMouseUp := TrayMouseUp;
    HintText := WidgetApplication.Title;
    HandleNeeded;
    VisibleTray := True;
  end;
end;

function TWidgetManager.Delete(WidgetForm: TWidgetMainForm): Integer;
begin
  Result := FFormList.IndexOf(WidgetForm);
  if Result >= 0 then
  begin
    FIniFile.EraseSection(WidgetForm.AmungusID);
    Result := FFormList.Remove(WidgetForm);
    FreeAndNil(WidgetForm);
  end;
end;

procedure TWidgetManager.DeleteAmungus(const AmungusId: WideString);
var
  Widget: TWidgetMainForm;
begin
  Widget := GetByAmungusId(AmungusId);
  if Widget <> nil then begin
    SendMessageW(Widget.Handle, WM_CLOSE, 0, 0);
    Self.Delete(Widget);
  end;
end;

procedure TWidgetManager.DeleteByHandle(const AHandle: HWND);
var
  Widget: TWidgetMainForm;
begin
  Widget := GetByHandle(AHandle);
  if Widget <> nil then begin
    SendMessageW(Widget.Handle, WM_CLOSE, 0, 0);
    Self.Delete(Widget);
  end;
end;

destructor TWidgetManager.Destroy;
begin
  if Assigned(WLang) then WLang.Free;
  FIniFile.Free;
  FFormList.Free;
  inherited Destroy;
end;

function TWidgetManager.GetByAmungusId(
  const AmungusId: WideString): TWidgetMainForm;
var
  I: Integer;
  WidgetForm: TWidgetMainForm;
begin
  Result := nil;
  for I := Self.Count - 1 downto 0 do
  begin
    WidgetForm := Self.Items[I];
    if Assigned(WidgetForm) and
      (WidgetForm.AmungusID = AmungusId) then Result := WidgetForm;
  end;
end;

function TWidgetManager.GetByHandle(const AHandle: HWND): TWidgetMainForm;
var
  I: Integer;
  WidgetForm: TWidgetMainForm;
begin
  Result := nil;
  for I := Self.Count - 1 downto 0 do
  begin
    WidgetForm := Self.Items[I];
    if Assigned(WidgetForm) and WidgetForm.HandleAllocated
       and (WidgetForm.Handle = AHandle) then Result := WidgetForm;
  end;
end;

function TWidgetManager.GetCount: Integer;
begin
  Result := FFormList.Count;
end;

function TWidgetManager.GetItem(Index: Integer): TWidgetMainForm;
begin
  Result := FFormList.Items[Index] as TWidgetMainForm;
end;

procedure TWidgetManager.HideForms;
var
  I: Integer;
  WidgetForm: TWidgetMainForm;
begin
  for I := Self.Count - 1 downto 0 do
  begin
    WidgetForm := Self.Items[I];
    if Assigned(WidgetForm) then PostMessageW(WidgetForm.Handle, WM_HIDEFORM, 0, 0);
    //Sleep(10);
  end;
end;

procedure TWidgetManager.Initialize;
var
  FileName: WideString;
  ASection, ATitle: WideString;
  AInitDelay: Integer;
  ALanguage: WideString;
  Values: TWStrings;
  I: Integer;
begin

  FileName := FConfigFolder + '\amungus.ini';
  Self.FFirstTime := not FileExists(FileName);

  FIniFile := TWMemIniFile.Create(FileName);
  ALanguage := FIniFile.ReadString('Config', 'Language', 'EN-US.INI');
  WLang.Change(ALanguage);

  AInitDelay := 250;

  Values := TWStringList.Create;
  try
    FIniFile.ReadSectionValues('Trackers', Values);
    for I := 0 to Values.Count - 1 do
    begin
      ASection := Values.Values[Values.Names[I]];
      if FIniFile.SectionExists(ASection) then
      begin
        ATitle := FIniFile.ReadString(ASection, 'Title', 'Amungus');
        AddAmungus(ASection, ATitle, AInitDelay);
        Inc(AInitDelay, 200);
        Sleep(20);
      end;
    end;
  finally
    Values.Free;
  end;
  UpdateWidgtesMenu;
  if Self.FFirstTime then ClickAddWidgetMenu(Self);
end;

procedure TWidgetManager.LoaderTimerExecute(Sender: TObject);
begin
  KillTimer(Self.Handle, IDT_LOADERTIMER);
  CheckVersion;
  CheckTracker;
end;

procedure TWidgetManager.ModifyLanguage;
begin
  ModifyMenuLanguage;
end;

procedure TWidgetManager.ModifyMenuLanguage;
var
  Menu: HMENU;
begin
  Menu := GetSubMenu(FMainMenu, 0);
  SetMenuText(Menu, MC_ABOUT, WLang[MC_ABOUT]);
  SetMenuText(Menu, MC_SHOW, WLang[MC_SHOW]);
  SetMenuText(Menu, MC_HIDE, WLang[MC_HIDE]);
  SetMenuText(Menu, MC_LANGUAGES, WLang[MC_LANGUAGES]);
  SetMenuText(Menu, MC_ADDWIDGET, WLang[MC_ADDWIDGET]);
  SetMenuText(Menu, MC_EXIT, WLang[MC_EXIT]);
end;

function TWidgetManager.ProcessMessage(var Msg: TMsg): Boolean;
begin
  Result := False;
  if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then
  begin
    Result := True;
    if Msg.Message <> WM_QUIT then
    begin
      TranslateMessage(Msg);
      DispatchMessage(Msg);
    end;
    //else FTerminated := True;
  end
  else WaitMessage; // WaitMessage olmazsa islemci kullanimi %100 e vurur.
end;

procedure TWidgetManager.ProcessMessages;
var
  Msg: TMsg;
begin
  while ProcessMessage(Msg) do {loop};
end;

procedure TWidgetManager.RightButtonClick(Sender: TObject);
var
  P: TPoint;
begin
  CreateMenu;
  if FMainMenu <> 0 then
  begin
    GetCursorPos(P);
    TrackPopupMenuEx(GetSubMenu(FMainMenu, 0),
      TPM_LEFTALIGN or TPM_LEFTBUTTON or TPM_VERTICAL,
      P.x, P.y, Self.Handle, nil);
  end;
end;

procedure TWidgetManager.SaveChanges;
var
  I: Integer;
  WidgetForm: TWidgetMainForm;
begin
  FIniFile.WriteString('Config', 'Language', WLang.FCurrent.ID);
  FIniFile.EraseSection('Trackers');
  for I := 0 to Self.Count - 1 do
  begin
    WidgetForm := Self.Items[I];
    if Assigned(WidgetForm) then
      with WidgetForm, FIniFile do
      begin
        EraseSection(Section);
        WriteString('Trackers', Format('Key%d', [I]), AmungusID);
        WriteInteger(Section, 'Left', Left);
        WriteInteger(Section, 'Top', Top);
        WriteBool(Section, 'AlwaysTop', AlwaysTop);
        WriteBool(Section, 'IgnoreMouse', IgnoreMouse);
        WriteBool(Section, 'PreventDragging', PreventDragging);
        WriteString(Section, 'Title', Title);
        WriteString(Section, 'AmungusID', AmungusID);
        WriteInteger(Section, 'Interval', Interval);
        WriteInteger(Section, 'Tracker', Tracker);
        WriteInteger(Section, 'Previous', Previous);
        WriteInteger(Section, 'Opacity', OpacityMax);
        WriteBool(Section, 'Enable', FEnableTracker);
        WriteString(Section, 'BackColor', Format('0x%0.8x', [BackColor]));
      end;
  end;
  FIniFile.UpdateFile;
end;

procedure TWidgetManager.ShowForms;
var
  I: Integer;
  WidgetForm: TWidgetMainForm;
begin
  for I := 0 to Self.Count - 1 do
  begin
    WidgetForm := Self.Items[I];
    if Assigned(WidgetForm) then PostMessageW(WidgetForm.Handle, WM_SHOWFORM, 0, 0);
    //Sleep(10);
  end;
end;

procedure TWidgetManager.TrayDblClick(Sender: TObject);
begin
  //WidgetForm.ClickShowHideMenu(Sender);
end;

procedure TWidgetManager.TrayMouseUp(Sender: TObject; Keys, X, Y: Integer);
begin
  if Keys and MK_RBUTTON <> 0 then
  begin
    SetActiveWindow(Self.Handle);
    SetForegroundWindow(Self.Handle);
    RightButtonClick(Self);
  end;
end;

procedure TWidgetManager.UpdateLangsMenu;
var
  I: Integer;
  Language: TWidgetLanguage;
  Text: WideString;
  SubMenu: HMENU;
  Checked: Boolean;
begin
  if FLangsMenu <> 0 then DestroyMenu(FLangsMenu);
  FLangsMenu := CreatePopupMenu();
  for I := 0 to WLang.FItems.Count - 1 do
  begin
    Language := WLang.FItems[I] as TWidgetLanguage;
    Text := Language.Name;
    AppendMenuW(FLangsMenu, MF_STRING, MC_LANGUAGE_START + I, PWideChar(Text));
    Checked := Language.ID = WLang.FCurrent.ID;
    CheckMenuItem(FLangsMenu, MC_LANGUAGE_START + I,
      MF_BYCOMMAND or CChecks[Checked]);
  end;
  SubMenu := GetSubMenu(FMainMenu, 0);
  ModifyMenuW(SubMenu, 2, MF_POPUP or MF_BYPOSITION or MF_STRING,
    FLangsMenu, PWideChar(WLang[MC_LANGUAGES]));
end;

procedure TWidgetManager.UpdateTrayMenu;
begin
  UpdateLangsMenu;
  UpdateWidgtesMenu;
end;

procedure TWidgetManager.UpdateWidgtesMenu;
var
  I: Integer;
  Widget: TWidgetMainForm;
  Text: WideString;
  SubMenu: HMENU;
begin
  if FWidgetsMenu <> 0 then DestroyMenu(FWidgetsMenu);
  FWidgetsMenu := CreatePopupMenu();
  if Self.Count > 0 then
  begin
    for I := 0 to Self.Count - 1 do
    begin
      Widget := Self.GetItem(I) as TWidgetMainForm;
      Text := Widget.Title;
      if Length(Text) = 0 then Text := WLang[IDS_TEXT_1007];
      Text := Text + WideFormat(' - (%s)', [Widget.AmungusID]);
      AppendMenuW(FWidgetsMenu, MF_STRING, MC_WIDGETS_START + I, PWideChar(Text));
    end;
  end
  else begin
    Text := WLang[IDS_TEXT_1008];
    AppendMenuW(FWidgetsMenu, MF_STRING, MC_WIDGETS_START,
      PWideChar(Text));
    EnableMenuItem(FWidgetsMenu, 0, MF_BYPOSITION or MF_GRAYED);
  end;
  SubMenu := GetSubMenu(FMainMenu, 0);
  ModifyMenuW(SubMenu, 5, MF_POPUP or MF_BYPOSITION or MF_STRING,
    FWidgetsMenu, PWideChar(WLang[MC_PREFRENCES]));
end;

procedure TWidgetManager.WMClose(var Message: TWidgetMessage);
begin
  FWidgetTray.VisibleTray := False;
  SaveChanges;
  HideForms;
  SendMessageW(FWidgetTray.Handle, WM_CLOSE, 0, 0);
  inherited WMClose(Message);
end;

procedure TWidgetManager.WMCommand(var Message: TWidgetMessage);
begin
  with Message do
    if HIWORD(wParam) = 0 then // from Menu
    begin
      case LOWORD(wParam) of
        MC_ABOUT: ClickAboutMenu(Self);
        MC_EXIT: ClickExitMenu(Self);
        MC_HIDE: ClickHideMenu(Self);
        MC_SHOW: ClickShowMenu(Self);
        MC_ADDWIDGET: ClickAddWidgetMenu(Self);
      else
        if LOWORD(wParam) >= MC_WIDGETS_START then
          ClickWidgetsMenu(Self, LOWORD(wParam))
        else ClickLangsMenu(Self, LOWORD(wParam));
      end;
    end;
end;

procedure TWidgetManager.WMDeleteWidget(var Message: TWidgetMessage);
begin
  DeleteByHandle(Message.LParam);
end;

procedure TWidgetManager.WMDestroy(var Message: TWidgetMessage);
var
  I: Integer;
  Form: TWidgetMainForm;
begin
  KillTimer(Self.Handle, IDT_LOADERTIMER);
  for I := 0 to Self.Count - 1 do
  begin
    Form := Self.Items[I];
    if Assigned(Form) then
    begin
      SendMessageW(Form.Handle, WM_CLOSE, 0, 0);
      Sleep(10);
    end;
  end;
  if Assigned(FThread) then
  begin
    if not FThread.Terminated then FThread.WaitFor;
    FreeAndNil(FThread);
  end;
  DestroyMenu(FLangsMenu);
  DestroyMenu(FWidgetsMenu);
  if FMainMenu <> 0 then DestroyMenu(FMainMenu);
  inherited WMDestroy(Message);
  PostQuitMessage(0);
end;

procedure TWidgetManager.WMDetails(var Message: TWidgetMessage);
var
  URL: WideString;
  WidgetForm: TWidgetMainForm;
begin
  WidgetForm := GetByHandle(Message.LParam);
  if Assigned(WidgetForm) then
  begin
    URL := 'http://whos.amung.us/stats/' + WidgetForm.AmungusID + '/';
    ShellExecuteW(Self.Handle, 'open', PWideChar(URL), nil, nil, SW_SHOW);
  end;
end;

procedure TWidgetManager.WMThreadDone(var Message: TWidgetMessage);
begin
  if Assigned(FThread) then
  begin
    //FThread.Request.Response.ContentStream.SaveToFile('tracker.png');
    FreeAndNil(FThread);
  end;
end;

procedure TWidgetManager.WMTimer(var Message: TWidgetMessage);
begin
  case Message.WParam of
    IDT_LOADERTIMER: LoaderTimerExecute(Self);
  end;
end;

procedure TWidgetManager.WMVersionDone(var Message: TWidgetMessage);
var
  XMLText: WideString;
  VersionText: string;
  MessageText: WideString;
  URL: WideString;
begin
  if Assigned(FVersionThread) then
  begin
    XMLText := FVersionThread.Request.Response.Content;
    FreeAndNil(FVersionThread);
  end;
  VersionText := ParseVersionXML(XMLText);
  if VersionText > WidgetVersion then
  begin
    MessageText := WLang[IDS_TEXT_1011];
    if MessageBoxW(Self.Handle, PWideChar(MessageText),
      'Amungus Desktop Widget', MB_YESNO or MB_ICONQUESTION) = IDYES then
    begin
      URL := 'http://www.shenturk.com/indir';
      ShellExecuteW(Self.Handle, 'open', PWideChar(URL), nil, nil, SW_SHOW);
    end;
  end;
end;

procedure TWidgetManager.WndProc(var Message: TWidgetMessage);
begin
  case Message.Msg of
    WM_TIMER: WMTimer(Message);
    WM_THREADDONE: WMThreadDone(Message);
    WM_VERSIONDONE: WMVersionDone(Message);
    WM_QUERYENDSESSION: Message.Result := 1;
    WM_ENDSESSION: if BOOL(Message.WParam) then SaveChanges;
    WM_COMMAND: WMCommand(Message);
    WM_DETAILS: WMDetails(Message);
    WM_DELETEWIDGET: WMDeleteWidget(Message);
  else
    inherited WndProc(Message);
  end;
end;

{ TWidgetApplication }

constructor TWidgetApplication.Create;
begin
  inherited Create;
  FTitle := 'Amungus Desktop Widget';
end;

destructor TWidgetApplication.Destroy;
begin
  inherited Destroy;
end;

procedure TWidgetApplication.Finalize;
begin
  Desktop.Free;
  CloseInternet;
  CoUninitialize;
  timeEndPeriod(FTimeCaps.wPeriodMin);
end;

procedure TWidgetApplication.FinalizeMutex;
begin
  if FMutex <> 0 then
  begin
    WaitForSingleObject(FMutex, 0);
    CloseHandle(FMutex);
  end;
end;

function TWidgetApplication.GetHandle: HWND;
begin
  Result := 0;
  if Assigned(WidgetManager) then
    Result := WidgetManager.Handle;
end;

function TWidgetApplication.GetRunning: Boolean;
begin
  Result := FRunning;
end;

procedure TWidgetApplication.Initialize;
begin

  InitCommonControls;
  // Call coinitialize on this thread
  if (CoInitFlags = -1) and (IsMultiThread) then
    CoInitFlags := COINIT_MULTITHREADED; // Required for multithreaded
  if Assigned(ComObj.CoInitializeEx) and (CoInitFlags <> -1) then
    ComObj.CoInitializeEx(nil, CoInitFlags)
  else CoInitialize(nil);

  timeGetDevCaps(@FTimeCaps, SizeOf(FTimeCaps));
  timeBeginPeriod(FTimeCaps.wPeriodMin); { Required for Sleep() function }

  SetCurrentDir(ExtractFilePath(ParamStr(0)));
  WLang := TWidgetLanguages.Create(Desktop);
  OpenInternet;

  Desktop := TWidgetDesktop.Create(nil);
  with Desktop do Name := 'Desktop';

  WidgetManager := TWidgetManager.Create(Desktop);
  WidgetManager.Name := 'WidgetManager';
  WidgetManager.ParentWindow := GetDesktopWindow();
  WidgetManager.HandleNeeded;
  WidgetManager.Initialize;

end;

procedure TWidgetApplication.InitializeMutex;
var
  LastError: DWORD;
begin
  FMutex := CreateMutexW(nil, False, WidgetMutexName);
  LastError := GetLastError;
  FRunning := LastError = ERROR_ALREADY_EXISTS;
end;

procedure TWidgetApplication.Run;
var
  Msg: TMsg;
  Window: HWND;
begin
  try
    InitializeMutex;
    try
      if not Running then
      begin
        Initialize;
        try
          //WidgetManager.Show;
          while GetMessage(Msg, 0, 0, 0) do
          begin
            TranslateMessage(Msg);
            DispatchMessage(Msg);
          end;
        finally
          Finalize;
        end;
      end
      else begin
        Window := FindWindowW(WidgetClassName, WidgetWindowName);
        if Window <> 0 then
          SendMessageW(Window, CM_RESTOREAPP, 0, 0);
      end;
    finally
      FinalizeMutex;
    end;
  except

  end;
end;

{ TWidgetLanguage }

constructor TWidgetLanguage.Create(const AID: WideString; IniFile: TWMemIniFile);
begin
  inherited Create;
  FID := AID;
  FIniFile := IniFile;
  FName := FIniFile.ReadString('Language', 'Display', '');
end;

destructor TWidgetLanguage.Destroy;
begin
  FIniFile.Free;
  inherited Destroy;
end;

function TWidgetLanguage.GetText(const Ident: Integer): WideString;
begin
  Result := FIniFile.ReadString('Language', WideFormat('%d', [Ident]), '');
end;

procedure TWidgetLanguage.SetText(const Ident: Integer;
  const Value: WideString);
begin
  FIniFile.WriteString('Language', WideFormat('%d', [Ident]), Value);
end;

{ TWidgetLanguages }

procedure TWidgetLanguages.Add(const FileName: WideString);
var
  WideText: WideString;
  WidgetLanguage: TWidgetLanguage;
  Strings: TWStringList;
  MemFile: TWMemIniFile;
  Stream: TResourceStream;
  //Stream: TMemoryStream;
  UniCode: WideChar;
begin
  Strings := TWStringList.Create;
  try
    Stream := TResourceStream.Create(MainInstance, FileName, 'LANGS');
    //Stream := TMemoryStream.Create;
    try
      //Stream.LoadFromFile('.\Amungus 1.50\' + FileName);
      Stream.Read(UniCode, SizeOf(WideChar));
      if UniCode <> BOM_LSB_FIRST then Stream.Seek(0, soFromBeginning);
      Strings.LoadFromStream(Stream);
      MemFile := TWMemIniFile.Create(FileName);
      MemFile.SetStrings(Strings);
      WideText := MemFile.ReadString('Language', 'Display', '');
      WidgetLanguage := TWidgetLanguage.Create(FileName, MemFile);
      FItems.Add(WidgetLanguage);
      FNames.Add(WideText + '=' + FileName);
      FCurrent := WidgetLanguage;
    finally
      Stream.Free;
    end;
  finally
    Strings.Free;
  end;
end;

procedure TWidgetLanguages.Change(const ID: WideString);
var
  Temp: TWidgetLanguage;
begin
  Temp := Find(ID);
  if Temp <> nil then FCurrent := Temp;
end;

constructor TWidgetLanguages.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FItems := TObjectList.Create(False);
  FNames := TWStringList.Create;
  FNames.Sorted := True;
  Initialize;
end;

destructor TWidgetLanguages.Destroy;
begin
  Release;
  FNames.Free;
  FItems.Free;
  inherited Destroy;
end;

function TWidgetLanguages.Find(const ID: WideString): TWidgetLanguage;
var
  I: Integer;
begin
  for I := 0 to FItems.Count - 1 do
  begin
    Result := FItems.Items[I] as TWidgetLanguage;
    if Result.ID = ID then Exit;
  end;
  Result := nil;
end;

function TWidgetLanguages.GetText(const Ident: Integer): WideString;
begin
  Result := '';
  if Assigned(FCurrent) then
    Result := FCurrent[Ident];
end;

procedure TWidgetLanguages.Initialize;
begin
  Add('EN-US.INI');
  Add('TR-TR.INI');
end;

procedure TWidgetLanguages.Release;
var
  I: Integer;
begin
  for I := 0 to FItems.Count - 1 do FItems[I].Free;
end;

procedure TWidgetLanguages.SetText(const Ident: Integer;
  const Value: WideString);
begin

end;

{ TAboutForm }

procedure TAboutForm.ControlHide(Control: TWidgetControl);
const
  Step = 8;
  Wait = 4;
begin
  while Control.Opacity > 0 do
  begin
    if Control.Opacity - Step <= 0 then
    begin
      Control.Opacity := 0;
      Self.Update;
      Break;
    end;
    Control.Opacity := Control.Opacity - Step;
    Self.Update;
    Sleep(Wait);
  end;
  Control.Hide;
end;

procedure TAboutForm.ControlShow(Control: TWidgetControl);
const
  Step = 8;
  Wait = 4;
begin
  Control.Show;
  while Control.Opacity < 255 do
  begin
    if Control.Opacity + Step >= 255 then
    begin
      Control.Opacity := 255;
      Self.Update;
      Break;
    end;
    Control.Opacity := Control.Opacity + Step;
    Self.Update;
    Sleep(Wait);
  end;
end;

constructor TAboutForm.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  Name := 'AboutForm';
  Width := 343;
  Height := 197;
  Left := (Desktop.WorkAreaWidth - Width) div 2;
  Top := (Desktop.WorkAreaHeight - Height) div 2;
end;

procedure TAboutForm.CreateControls;
begin

  Background := TWidgetImageControl.Create(Self);
  with Background do
  begin
    Parent := Self;
    OnMouseDown := DoMouseDown;
    FileName := 'ABOUT.PNG';
    Width := 343;
    Height := 197;
    Left := 0;
    Top := 0;
    Opacity := 255;
    Visible := True;
  end;

  TitleLabel := TWidgetLabel.Create(Self);
  with TitleLabel do
  begin
    Parent := Self;
    Width := (Self.Width div 5) * 4;
    Height := Self.Height div 2;
    Left := Self.Width - Width - 20;
    Top := 20;//(Self.Height - Height) div 2;
    with Canvas do begin
      Font.Format.Alignment := StringAlignmentFar;
      Font.Format.LineAlignment := StringAlignmentCenter;
      Font.Name := 'Impact';//'Arial Unicode MS';//'Trebuchet MS'//
      Font.Size := 26;
      Font.Color := $EFFFFFFF;
    end;
    Caption := 'Amung.us Desktop Widget';
    Enabled := False;
    //Border := True;
    Shadow := True;
    Visible := True;
  end;

  VersionLabel := TWidgetLabel.Create(Self);
  with VersionLabel do
  begin
    Parent := Self;
    Width := (Self.Width div 5) * 4;
    Height := 20;
    Left := Self.Width - Width - 20;
    Top := TitleLabel.Top + TitleLabel.Height - 8;
    with Canvas do begin
      Font.Format.Alignment := StringAlignmentFar;
      Font.Format.LineAlignment := StringAlignmentCenter;
      Font.Name := 'Trebuchet MS';//'Impact';//'Arial Unicode MS';//
      Font.Size := 8;
      Font.Color := $EFFFFFFF;
    end;
    Caption := 'Version ' + WidgetVersion;
    Enabled := False;
    //Border := True;
    Shadow := True;
    Visible := True;
  end;

  CopyrightLabel := TWidgetLabel.Create(Self);
  with CopyrightLabel do
  begin
    Parent := Self;
    Width := (Self.Width div 5) * 4;
    Height := 20;
    Left := Self.Width - Width - 20;
    Top := VersionLabel.Top + VersionLabel.Height;
    with Canvas do begin
      Font.Format.Alignment := StringAlignmentFar;
      Font.Format.LineAlignment := StringAlignmentCenter;
      Font.Name := 'Trebuchet MS';//'Impact';//'Arial Unicode MS';//
      Font.Size := 8;
      Font.Color := $EFFFFFFF;
    end;
    Caption := 'Copyright © 2008 freedelphi';
    Enabled := False;
    //Border := True;
    Shadow := True;
    Visible := True;
  end;

  HomepageLabel := TWidgetLabel.Create(Self);
  with HomepageLabel do
  begin
    Parent := Self;
    OnClick := HomepageLabelClick;
    Width := (Self.Width div 5) * 4;
    Height := 20;
    Left := Self.Width - Width - 20;
    Top := CopyrightLabel.Top + CopyrightLabel.Height;
    with Canvas do begin
      Font.Format.Alignment := StringAlignmentFar;
      Font.Format.LineAlignment := StringAlignmentCenter;
      Font.Name := 'Trebuchet MS';//'Impact';//'Arial Unicode MS';//
      Font.Size := 8;
      Font.Color := $EFFFFF00;
    end;
    Caption := 'http://www.shenturk.com';
    Cursor := LoadCursor(0, IDC_HAND);
    Shadow := True;
    Visible := True;
  end;


end;

procedure TAboutForm.CreateForm;
begin
  inherited CreateForm;
  CreateControls;
end;

destructor TAboutForm.Destroy;
begin
  inherited Destroy;
end;

procedure TAboutForm.DoMouseDown(Sender: TObject; Keys, X, Y: Integer);
begin
  HideForm;
end;

procedure TAboutForm.HideForm;
const
  Step = 8;
  Wait = 4;
begin
  while Self.Opacity > 0 do
  begin
    if Self.Opacity - Step <= 0 then
    begin
      Self.Opacity := 0;
      Self.UpdateForm;
      Break;
    end;
    Self.Opacity := Self.Opacity - Step;
    Self.UpdateForm;
    Sleep(Wait);
  end;
  Self.Hide;
end;

procedure TAboutForm.HomepageLabelClick(Sender: TObject; Keys, X,
  Y: Integer);
var
  URL: WideString;
begin
  HideForm;
  URL := 'http://www.shenturk.com/?ref=amungus';
  ShellExecuteW(WidgetManager.Handle, 'open', PWideChar(URL), nil, nil, SW_SHOW);
end;

procedure TAboutForm.PaintWindow;
begin
  inherited PaintWindow;
  //Canvas.FillRectangle(Self.ClientRect);
end;

procedure TAboutForm.ShowForm;
const
  Step = 8;
  Wait = 4;
begin
  Self.Show;
  TitleLabel.Opacity := 0;
  VersionLabel.Opacity := 0;
  CopyrightLabel.Opacity := 0;
  HomepageLabel.Opacity := 0;
  SetForegroundWindow(Self.Handle);
  SetActiveWindow(Self.Handle);
  Self.Update;
  while Self.Opacity < 255 do
  begin
    if Self.Opacity + Step >= 255 then
    begin
      Self.Opacity := 255;
      Self.UpdateForm;
      Break;
    end;
    Self.Opacity := Self.Opacity + Step;
    Self.UpdateForm;
    Sleep(Wait);
  end;
  Sleep(50);
  ControlShow(TitleLabel);
  ControlShow(VersionLabel);
  ControlShow(CopyrightLabel);
  ControlShow(HomepageLabel);
end;

end.

