unit U_Progress;

interface

uses
  Windows, U_LNG, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, cxControls, cxContainer, cxEdit, cxLabel, ExtCtrls, RzPanel,
  ComCtrls, siComp, siLngLnk, cxGraphics, cxLookAndFeels, cxLookAndFeelPainters;

type
  TF_Progress = class(TForm)
    pnCaption: TRzPanel;
    lbProgressCaption: TcxLabel;
    ProgressBar: TProgressBar;
    lng_Forms: TsiLangLinked;
    Timer_ActiveForm: TTimer;
    procedure FormShow(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormActivate(Sender: TObject);
    procedure FormDeactivate(Sender: TObject);
    procedure CreateParams(var Params: TCreateParams); override;
    procedure Timer_ActiveFormTimer(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    FCurrProgressPos: Integer;
    FMaxProgressPos: Integer;
    FLockedFormHandles: TList;
  public
    { Public declarations }
    FPauseCount: Integer;
    procedure Action(var Msg: TMsg; var Handled: boolean);
    procedure LockVisibleForms;
    procedure UnLockForms;
    procedure PauseProgress(APaused: Boolean);
    procedure SetTop;
    //Tolik
//    procedure StartProgress(ACaption: String; AMaxPos: Integer);
    procedure StartProgress(ACaption: String; AMaxPos: Integer; MustShowProgress: Boolean = False);
    procedure REShowProgress(ACaption: String; AMaxPos: Integer; MustShowProgress: Boolean = False);
    //
    procedure StepProgress;
    procedure StopProgress;
  end;

var
  F_Progress: TF_Progress;

implementation
uses U_Constants, U_Common, {Tolik--23/11/2016 -- }U_Main;

{$R *.dfm}


procedure TF_Progress.FormShow(Sender: TObject);
begin
  //Application.OnMessage := Action;
  //Application.RestoreTopMosts;
end;

procedure TF_Progress.FormActivate(Sender: TObject);
begin
  if FPauseCount = 0 then
  begin
    SetTop;
    Refresh;
  end;  
end;

procedure TF_Progress.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  //Application.OnMessage := Nil;
end;

procedure TF_Progress.Action(var Msg: TMsg; var Handled: boolean);
var
  CurrActiveWindow: THandle;
begin
  (*if (Msg.message = WM_LBUTTONDOWN) or (Msg.message = WM_LBUTTONDBLCLK) or
     (Msg.message = WM_RBUTTONDOWN) or (Msg.message = WM_RBUTTONDBLCLK) or
     (Msg.message = WM_KEYDOWN) or (Msg.message = WM_MOUSEWHEEL) then
  begin
    if (Msg.wParam <> 9){MK_CONTROL} then
    begin
      Msg.message := 0;
      Msg.wParam := 0;
    end;
  end;*)

  if (Msg.message = WM_LBUTTONDOWN) or (Msg.message = WM_LBUTTONDBLCLK) or
     (Msg.message = WM_RBUTTONDOWN) or (Msg.message = WM_RBUTTONDBLCLK) or
     //(Msg.message = WM_NCLBUTTONDOWN) or (Msg.message = WM_NCLBUTTONUP) or
     (Msg.message = WM_KEYDOWN) or (Msg.message = WM_MOUSEWHEEL) {or
     ((Msg.message >= WM_KEYFIRST) and (Msg.message <= WM_KEYLAST)) or
     ((Msg.message >= WM_MOUSEFIRST) and (Msg.message <= WM_MOUSELAST))} {or
     (Msg.message = WM_ACTIVATE) or (Msg.message = WM_SETFOCUS)}
      then
  begin
    if (Msg.wParam <> 9){MK_CONTROL} then
    begin
      Msg.message := 0;
      Msg.wParam := 0;
      //Handled := true;
    end;
  end;
end;

procedure TF_Progress.LockVisibleForms;
var
  i: integer;
  Form: TCustomForm;
begin
  FLockedFormHandles.Clear;
  for i := 0 to Screen.CustomFormCount - 1 do
  begin
    Form := Screen.CustomForms[i];
    if Form is TForm then
      //if Form.ClassName = 'TFSCS_Main' then
      //if Form.ClassName <> 'TF_MakeEditCrossConnection' then
      if Form <> Self then
        if TForm(Form).Visible then
          if IsWindowEnabled(Form.Handle) then
          begin
            FLockedFormHandles.Add(Pointer(Form.Handle));
            EnableWindow(Form.Handle, False);
          end;
  end;
end;

procedure TF_Progress.UnLockForms;
var
  i: Integer;
  // tolik 28/04/2017 --
  function GetFormFromHandle(Handle: HWnd): TForm;
  var
    wc: TWinControl;
  begin
    wc := FindControl(Handle);
    if (wc is TForm)
      then Result := TForm(wc)
      else Result := nil;
  end;
  //
begin
  for i := FLockedFormHandles.Count - 1 downto 0 do
  begin
    if GetFormFromHandle(HWnd(FLockedFormHandles[i])) <> nil then
      EnableWindow(HWnd(FLockedFormHandles[i]), true);
  end;
  //for i := 0 to FLockedFormHandles.Count - 1 do
  //  EnableWindow(HWnd(FLockedFormHandles[i]), true);
  FLockedFormHandles.Clear;
end;

procedure TF_Progress.PauseProgress(APaused: Boolean);
begin
  case APaused of
    true:
      begin
        if FPauseCount = 0 then
        begin
          Application.OnMessage := Nil;
          UnLockForms;
        end;
        Inc(FPauseCount);
        //F_Progress.Hide;
      end;
    false:
      begin
        if FPauseCount > 0 then
        begin
          Dec(FPauseCount);
          if FPauseCount = 0 then
          begin
            Application.OnMessage := F_Progress.Action;
            LockVisibleForms;

            if Not F_Progress.Visible or Not F_Progress.Showing then
              F_Progress.Show;
            F_Progress.Refresh;

            //if GetForegroundWindow <> F_Progress.Handle then
            //  SetForegroundWindow(F_Progress.Handle);
          end;
        end;
      end;
  end;
end;

procedure TF_Progress.SetTop;
begin
  //SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE);
  //SetWindowPos(Handle, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOACTIVATE or
  //  SWP_NOOWNERZORDER or SWP_SHOWWINDOW or SWP_NOZORDER);


end;
//Tolik
//procedure TF_Progress.StartProgress(ACaption: String; AMaxPos: Integer);
procedure TF_Progress.StartProgress(ACaption: String; AMaxPos: Integer; MustShowProgress: Boolean = False);

begin
  if ACaption <> '' then
  begin
    //lbProgressCaption.Caption := ACaption;
    pnCaption.Caption := ACaption;
  end
  else
  begin
    //lbProgressCaption.Caption := cProgress_Mes1;
    pnCaption.Caption := cProgress_Mes1;
  end;

  FCurrProgressPos := 0;
  FMaxProgressPos := 0;
  ProgressBar.Visible := AMaxPos > 0;
  if AMaxPos > 0 then
  begin
    FMaxProgressPos := AMaxPos + Round((AMaxPos / 100) * 5);
    ProgressBar.Position := FCurrProgressPos;
    // Application.ProcessMessages;
    ProcessMessagesEx;
  end;

  //SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOZORDER or SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE);
  //SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE);

  //FormStyle := fsStayOnTop;
  //Application.RestoreTopMosts;

  Application.OnMessage := Action;
  //OnDeactivate := FormDeactivate;
  //LockVisibleForms;

//  Self.Position := poDesktopCenter;

  {$IF Not Defined(BASEADM_SCS)}
//    if Not ProgressBar.Visible then
    if ((Not ProgressBar.Visible) and (not MustShowProgress)) then
      Self.Top := -100
    else
      Self.Position := poMainFormCenter;
  {$ELSE}
    Self.Position := poMainFormCenter;
  {$IFEND}

  Show;
  {$IF Not Defined(BASEADM_SCS)}
//    if Not ProgressBar.Visible then
    if ((Not ProgressBar.Visible) and (not MustShowProgress)) then
    begin
      Self.Top := -100;
      Cursor := crHourGlass;
    end;
  {$ELSE}
  {$IFEND}

  SetActiveWindow(Self.Handle); //SetForegroundWindow(Self.Handle);
  LockVisibleForms;
  //Application.ProcessMessages;
  ProcessMessagesEx;
end;

//Tolik
procedure TF_Progress.REShowProgress(ACaption: String; AMaxPos: Integer; MustShowProgress: Boolean = False);
begin
  //Tolik
  //if (Self.Top = -100) then
  //
  begin
    if ACaption <> '' then
    begin
      pnCaption.Caption := ACaption;
    end
    else
    begin
      pnCaption.Caption := cProgress_Mes1;
    end;

    FCurrProgressPos := 0;
    FMaxProgressPos := 0;
    //Tolik
    ProgressBar.Position := 0;
    //
    ProgressBar.Visible := AMaxPos > 0;
    if AMaxPos > 0 then
    begin
      FMaxProgressPos := AMaxPos + Round((AMaxPos / 100) * 5);
      ProgressBar.Position := FCurrProgressPos;
     // Application.ProcessMessages;
      ProcessMessagesEx;
    end;

    Self.Position := poMainFormCenter;

    Show;
    Cursor := crHourGlass;
    ProcessMessagesEx;
    //SetActiveWindow(Self.Handle);
   // Application.ProcessMessages;
  end;  
end;


procedure TF_Progress.StepProgress;
begin
  Inc(FCurrProgressPos);
  ProgressBar.Position := Round(FCurrProgressPos/FMaxProgressPos * 100);
  F_Progress.Repaint;
  F_Progress.Refresh;
end;

procedure TF_Progress.StopProgress;
begin
  //OnDeactivate := nil;
  try
    if Visible then
    begin
      if FMaxProgressPos > 0 then
      begin
        ProgressBar.Position := 100;
        Application.ProcessMessages;
        Sleep(500);
        ProgressBar.Position := 0;
      end;
      UnLockForms;

      //22.08.2012 Close;
      Application.OnMessage := Nil;
      Application.ProcessMessages;
      Close;
    end;
  finally
    UnLockForms;
  end;
  {$IF Defined(SCS_PE)}
    Cursor := crDefault;
  {$IFEND}
end;

procedure TF_Progress.FormDeactivate(Sender: TObject);
begin
  //if Showing then
  //  SetForegroundWindow(Handle);


  Timer_ActiveForm.Enabled := true;
  ProcessMessagesEx;
end;

procedure TF_Progress.CreateParams(var Params: TCreateParams); 
begin
  Inherited CreateParams(Params);
end;

procedure TF_Progress.Timer_ActiveFormTimer(Sender: TObject);
begin
  TTimer(Sender).Enabled := false;

  if Visible then
    if Screen.ActiveForm <> Self then
      SetActiveWindow(Handle);
end;

procedure TF_Progress.FormCreate(Sender: TObject);
begin
  FLockedFormHandles := TList.Create;
  FPauseCount := 0;
  
end;

procedure TF_Progress.FormDestroy(Sender: TObject);
begin
  FreeAndNil(FLockedFormHandles);
end;

end.
