AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

"Unendlicher Progressbar"

Ein Thema von skoschke · begonnen am 8. Jul 2020 · letzter Beitrag vom 27. Jul 2020
Antwort Antwort
Seite 6 von 6   « Erste     456   
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#51

AW: "Unendlicher Progressbar"

  Alt 10. Jul 2020, 19:23
Bei der Variante "im Timer anzeigen was der Thread macht" schon.
$2B or not $2B
  Mit Zitat antworten Zitat
Benmik

Registriert seit: 11. Apr 2009
560 Beiträge
 
Delphi 12 Athens
 
#52

AW: "Unendlicher Progressbar"

  Alt 10. Jul 2020, 19:40
Die Variante "eine langdauernde Operation muss unbedingt im MainThread laufen" ist offenbar äußerst blöd. Mir scheint, entweder man greift zu furchtbaren Verrenkungen oder man sendet einfach abschnittsweise aus dem MainThread. Mir persönlich wären die Verrenkungen für eine schlichte Anwenderinformation zu aufwändig.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#53

AW: "Unendlicher Progressbar"

  Alt 10. Jul 2020, 22:50
Ja ist blöd, ohne regelmäßig etwas Zeit der VCL zu geben, um sich zu aktualisieren und Messages zu verarbeiten.

Gennauso unpraktisch, wie letztens mal jemand es machte.
* im Thread arbeiten, aber praktisch alles dort wurde via Synchronize im Haupthtread ausgeführt, was dann ebenfalls diesen extrem überlastete, ohne dass der Thread was zu tun hatte.
* Ergebnis war dass es langsamer war, durch die masse an Synchronisierungen, und der Hauptthread ebenfalls hing, weil viele der Einzelschritte zu lang waren
$2B or not $2B

Geändert von himitsu (10. Jul 2020 um 23:03 Uhr)
  Mit Zitat antworten Zitat
Jumpy

Registriert seit: 9. Dez 2010
Ort: Mönchengladbach
1.737 Beiträge
 
Delphi 6 Enterprise
 
#54

AW: "Unendlicher Progressbar"

  Alt 13. Jul 2020, 09:48
Nur nochmal zur Klarstellung: Es geht um das Starten der Anwendung? Oder geht es um Prozesse innerhalb der Anwendung, wo nach einem Button-Klick irgendwas passieren soll?
Ralph
  Mit Zitat antworten Zitat
philipp.hofmann

Registriert seit: 21. Mär 2012
Ort: Hannover
898 Beiträge
 
Delphi 10.4 Sydney
 
#55

AW: "Unendlicher Progressbar"

  Alt 13. Jul 2020, 13:41
Zur Timer-Variante:
Zitat:
und den Zugriff auf diese Variablen müsste man dennoch synchronisieren
Da es "nur" um die Status-Anzeige geht, sichere ich die Abfrage und Aktualisierungen mit try-catch ab.
Wenn dann mal ein Status-Update daneben geht, ist nicht weiter tragisch.
Aber natürlich geht dies nur, wenn der Hauptthread an sich "Zeit" hat, damit der Timer feuern kann.
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.648 Beiträge
 
Delphi 11 Alexandria
 
#56

AW: "Unendlicher Progressbar"

  Alt 13. Jul 2020, 14:11
Mein Vorschlag von oben mit einem Fenster im Thread zur Statusanzeige wie mit den verlinkten Komponenten wird übrigens auch von Notepad++ und anderen so verwendet. Dort hängt das restliche Hauptfenster ebenfalls, in dem Fall bei der Suche in vielen Dateien.

Vor allem müsste dafür am wenigsten geändert werden...
Sebastian Jänicke
AppCentral
  Mit Zitat antworten Zitat
Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.691 Beiträge
 
Delphi 11 Alexandria
 
#57

AW: "Unendlicher Progressbar"

  Alt 17. Jul 2020, 12:55
Hi, das Thema ist zwar schon ein wenig her, dennoch habe ich mir mal die Mühe gemacht eine kleine Klasse für genau diesen Zweck zu erschaffen, sehr Resourcenschonend da WinApi genutzt wurde.
Also dieser Zweck wird erfüllt: Ein Programm braucht einen "unendlichen" ProgressBar der per Code oder per Dialog auch abgebrochen werden kann, zusätzlich hat man ein Label zur freien Verfügung.

Es wurde TThread und WinApi genutzt um ans Ziel zu kommen, plus Resource Dialoge als Anzeige.


Hier ist der Quelltext der Klasse, im Download ist der Source kommentiert.
Delphi-Quellcode:
(*
example usage:
uses
  kzSplashBar;

procedure TForm1.FormCreate(Sender: TObject);
var
  sb: TSplashBar;
begin
  sb := TSplashBar.Create(Handle, 'example SplashBar Caption', True);
  Sleep(5000); // simulate a blocking main thread
  sb.Terminate;
end;
*)


unit kzSplashBar;

interface

uses
  Winapi.Windows, Winapi.Messages, Winapi.CommCtrl, System.Classes
  ;

type
  TSplashBar = class(System.Classes.TThread)
  private
    FhDlg: HWND;
    FMarqueeSpeed: Integer;
    FLabelCaption: string;
    FButtonCaption: string;
    FShowButton: Boolean;
    FMarqueeMode: Boolean;
    FParentHandle: HWND;
    FAborted: Boolean;
    FFlash: Boolean;
    FForeGround: Boolean;
  protected
    procedure Execute; override;
    procedure ShowSplashBar;
    procedure SetMarqueeSpeed(const ASpeed: Integer);
    procedure SetLabelCaption(const ACaption: string);
    procedure SetButtonCaption(const ACaption: string);
    function SetCaption(const AControlId: Cardinal; const ACaption: string): Boolean;
  public
    constructor Create(const AParentHandle: HWND; const ALabelCaption: string; const AEnableMarquee: Boolean); overload;
    constructor Create(const AParentHandle: HWND; const ALabelCaption: string; const AButtonCaption: string; const AEnableMarquee: Boolean); overload;
    property MarqueeSpeed: Integer read FMarqueeSpeed write SetMarqueeSpeed;
    property MarqueeMode: Boolean read FMarqueeMode;
    property LabelCaption: string read FLabelCaption write SetLabelCaption;
    property ButtonCaption: string read FButtonCaption write SetButtonCaption;
    property Aborted: Boolean read FAborted;
    property AutoForeGround: Boolean read FForeGround write FForeGround;
    property AutoFlash: Boolean read FFlash write FFlash;
    procedure SetProgressBarColor(const ARed: Byte; const AGreen: Byte; const ABlue: Byte);
    procedure SetProgressBarBkColor(const ARed: Byte; const AGreen: Byte; const ABlue: Byte);
    procedure SetProgressBarRange(const AMax: Integer);
    procedure SetProgressBarPosition(const APosition: Integer);
    procedure SetProgressBarStep;

  end;

implementation

// include needed external resource dialog file
{$R *.res}

const
  IDD_SMOOTH = 1000;
  IDD_MARQUEE = 1001;
  IDD_SMOOTHBUTTON = 1010;
  IDD_MARQUEEBUTTON = 1011;
  IDC_LABEL = 2000;
  IDC_PB = 2001;
  IDC_BUTTON = 2002;

var
  LAborted: Boolean = False;

{ TSplashBar }

constructor TSplashBar.Create(const AParentHandle: HWND; const ALabelCaption: string; const AEnableMarquee: Boolean);
begin
  FShowButton := False;
  FLabelCaption := ALabelCaption;
  FButtonCaption := '';
  FAborted := False;
  LAborted := False;
  FFlash := False;
  FForeGround := False;
  FMarqueeSpeed := 0;
  FParentHandle := AParentHandle;
  FMarqueeMode := AEnableMarquee;
  inherited Create(False);
  FreeOnTerminate := True;
end;

constructor TSplashBar.Create(const AParentHandle: HWND; const ALabelCaption: string; const AButtonCaption: string; const AEnableMarquee: Boolean);
begin
  FShowButton := True;
  FLabelCaption := ALabelCaption;
  FButtonCaption := AButtonCaption;
  FAborted := False;
  LAborted := False;
  FFlash := False;
  FForeGround := False;
  FMarqueeSpeed := 0;
  FParentHandle := AParentHandle;
  FMarqueeMode := AEnableMarquee;
  inherited Create(False);
  FreeOnTerminate := True;
end;

procedure TSplashBar.Execute;
var
  Msg: TMsg;
begin
  ShowSplashBar;
  while ((not Terminated) and
          GetMessage(Msg, FhDlg, 0, 0))) do
    begin
      TranslateMessage(Msg);
      DispatchMessage(Msg);
    end;
  FAborted := LAborted;
  EndDialog(FhDlg, 0);
  if AutoForeGround then
    SetForegroundWindow(FParentHandle);
  if AutoFlash then
    FlashWindow(FParentHandle, BOOL(True));
end;

function TSplashBar.SetCaption(const AControlId: Cardinal; const ACaption: string): Boolean;
begin
  Result := SetWindowText(
              GetDlgItem(FhDlg, AControlId),
              PChar(ACaption)
            );
end;

procedure TSplashBar.SetMarqueeSpeed(const ASpeed: Integer);
begin
  if (ASpeed >= 0) then
    begin
      FMarqueeSpeed := ASpeed;
      SendDlgItemMessage(FhDlg, IDC_PB, PBM_SETMARQUEE, 1, FMarqueeSpeed);
    end;
end;

procedure TSplashBar.SetProgressBarColor(const ARed: Byte; const AGreen: Byte; const ABlue: Byte);
begin
  SendDlgItemMessage(FhDlg, IDC_PB, PBM_SETBARCOLOR, 1, RGB(ARed, AGreen, AGreen));
end;

procedure TSplashBar.SetProgressBarBkColor(const ARed: Byte; const AGreen: Byte; const ABlue: Byte);
begin
  SendMessage(GetDlgItem(FhDlg, IDC_PB), PBM_SETBKCOLOR, 1, RGB(ARed, AGreen, AGreen));
end;

procedure TSplashBar.SetProgressBarRange(const AMax: Integer);
begin
  SendMessage(GetDlgItem(FhDlg, IDC_PB), PBM_SETRANGE32, 0, AMax);
  SendMessage(GetDlgItem(FhDlg, IDC_PB), PBM_SETRANGE, 0, MakeLParam(0, AMax));
  SendMessage(GetDlgItem(FhDlg, IDC_PB), PBM_SETSTEP, WPARAM(AMax div 10), 0);
end;

procedure TSplashBar.SetProgressBarPosition(const APosition: Integer);
begin
  SendMessage(GetDlgItem(FhDlg, IDC_PB), PBM_SETPOS, APosition, 0);
end;

procedure TSplashBar.SetProgressBarStep;
begin
  SendMessage(GetDlgItem(FhDlg, IDC_PB), PBM_STEPIT, 0, 0);
end;

procedure TSplashBar.SetLabelCaption(const ACaption: String);
begin
  FLabelCaption := ACaption;
  SetCaption(IDC_LABEL, FLabelCaption);
end;

procedure TSplashBar.SetButtonCaption(const ACaption: string);
begin
  if FShowButton then
    begin
      FButtonCaption := ACaption;
      SetCaption(IDC_BUTTON, FButtonCaption);
     end;
end;

function DlgFunc(hWin: HWND; uMsg: UINT; wp: WPARAM; lp: LPARAM): bool; stdcall;
begin
  Result := BOOL(False);
  case uMsg of
    WM_CREATE:
      begin
      end; // WM_CREATE

    WM_INITDIALOG:
      begin
      end; // WM_INITDIALOG

    WM_ACTIVATE:
      begin
      end; // WM_ACTIVATE

    WM_LBUTTONDOWN:
      begin
        Result := BOOL(DefWindowProc(hWin, uMsg, wp, lp));
        PostMessage(hWin, WM_SYSCOMMAND, $f012, 0);
      end; // WM_LBUTTONDOWN

    WM_PAINT, WM_NCPAINT, WM_NCACTIVATE:
      begin
        InvalidateRect(hWin, nil, True);
      end; // WM_PAINT, WM_NCPAINT, WM_NCACTIVATE

    WM_SIZE:
      begin
        MoveWindow(hWin, 0, HiWord(lp), LOWORD(lp), HiWord(lp), True);
      end; // WM_SIZE

    WM_COMMAND: // react on controls command, like buttons or checkboxes etc may invoke
      begin
        case LoWord(wp) of // what shall happen when a CONTROL_ID triggered WM_COMMAND
          IDC_BUTTON:
            begin
              if (MessageBox(hWin,
                             PChar(
                                   'Would you like to cancel operation?'+#13#10#13#10
                                  +'(keep in mind that current operation may finish first.)'
                                  ),
                             PChar('Cancel Operation'),
                         MB_YESNO or MB_ICONQUESTION or MB_TOPMOST or MB_APPLMODAL)
                  = ID_YES) then
              begin
                LAborted := True;
                PostQuitMessage(0);
              end;
            end; // ID_BUTTON
        end; // case LoWord(wp)
      end; // WM_COMMAND

    WM_CLOSE, WM_DESTROY:
      begin
       end; // WM_CLOSE, WM_DESTROY
  end; // case uMsg
end;

procedure TSplashBar.ShowSplashBar;
var
  hWndFont: HGDIOBJ;
begin
  InitCommonControls;
  if (not FShowButton and FMarqueeMode) then
    FhDlg := CreateDialogParam(HInstance,
               MakeIntResource(IDD_MARQUEE),
               GetDesktopWindow, @DlgFunc, 0);

  if (not FShowButton and not FMarqueeMode) then
    FhDlg := CreateDialogParam(HInstance,
               MakeIntResource(IDD_SMOOTH),
               GetDesktopWindow, @DlgFunc, 0);

  if (FShowButton and FMarqueeMode) then
    FhDlg := CreateDialogParam(HInstance,
               MakeIntResource(IDD_MARQUEEBUTTON),
               GetDesktopWindow, @DlgFunc, 0);

  if (FShowButton and not FMarqueeMode) then
    FhDlg := CreateDialogParam(HInstance,
               MakeIntResource(IDD_SMOOTHBUTTON),
               GetDesktopWindow, @DlgFunc, 0);


  if (FhDlg <= 0) then
    Exit;
  SetLabelCaption(FLabelCaption);
  if FShowButton then
    SetButtonCaption(FButtonCaption);
  SetMarqueeSpeed(FMarqueeSpeed);
  hWndFont := GetStockObject(DEFAULT_GUI_FONT);
  if(hWndFont <> 0) then
    SendMessage(FhDlg, WM_SETFONT, hWndFont, LPARAM(True));
end;

end.
Im Anhang ist ein kommentiertes Demo Projekt samt allen Quelltexten plus 32bit Kompilat zum reinschnuppern was die Klasse macht.
Angehängte Dateien
Dateityp: 7z SplashBar.7z (691,8 KB, 26x aufgerufen)
Gruß vom KodeZwerg
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.648 Beiträge
 
Delphi 11 Alexandria
 
#58

AW: "Unendlicher Progressbar"

  Alt 21. Jul 2020, 17:58
Es wurde TThread und WinApi genutzt um ans Ziel zu kommen, plus Resource Dialoge als Anzeige.
Genau das habe ich auch in der verlinkten MTCL gemacht, nur dass ich die visuellen Komponenten in Klassen verpackt habe und man damit auf die Komponenten in der Ressource zugreifen kann. Alternativ kann man die Komponenten aber auch dynamisch erstellen. Aber das Projekt ist eben noch nicht weit.

Die Demo sieht gut aus, so hatte ich mir das vorgestellt.
Sebastian Jänicke
AppCentral
  Mit Zitat antworten Zitat
Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.691 Beiträge
 
Delphi 11 Alexandria
 
#59

AW: "Unendlicher Progressbar"

  Alt 27. Jul 2020, 08:39
Genau das habe ich auch in der verlinkten MTCL gemacht, nur dass ich die visuellen Komponenten in Klassen verpackt habe und man damit auf die Komponenten in der Ressource zugreifen kann. Alternativ kann man die Komponenten aber auch dynamisch erstellen. Aber das Projekt ist eben noch nicht weit.

Die Demo sieht gut aus, so hatte ich mir das vorgestellt.
Wiedermal sorry für späten reply.... bissl Ferien zwischendurch mal

Ich wollte echt nicht in Konkurrenz mit Dir stehen, dennoch vielen Dank für's Lob, für mich ist es eh die einzig wahre Möglichkeit an so etwas ranzugehen.
Da man auch im Urlaub Zeit mit Delphi verbringt hab ich nochmal von vorne angefangen (aufm Lappi fehlte mir meine vorige Kreation, ohne inet konnt ichs nicht laden), dieses mal gleich als Komponente.
Nach einem Diagram wie ich es mir vorgestellt habe das es zu funktionieren hat, nun auch als "Zwei-Klassen-System" falls man das so nennt.
Hauptklasse ist für die Delphi IDE als Wrapper, intern die eigentliche Klasse.
Nun auch 100% dynamisch ohne Resourcen-Dialog. Da hier und da noch ein paar ungereimtheiten vorhanden sind die mir nicht zusagen gibt es im Anhang nur eine Demo.
Falls daran überhaupt ein Interesse bestehen sollte, werde ich den Source auch zur freien Verfügung hochladen.

Die drei Punkte die mir noch Sorgen bereiten:
- 1. Wenn ich das Window auf der TaskBar eintrage, kann man den Dialog über der TaskBar schließen... das geht so mal gar nicht.
- 2. Bild positionierung klappt noch nicht so wie ich es gerne hätte.
// edit: mit Bild positionierung meine ich nicht was Window sondern meine Unterstützung für Bilder im Splash
// am liebsten würde ich eine "Stretch" methode implementieren, da fehlt mir noch bissl Erfahrung how-to, aber wird schon noch
- 3. Die GUI nochmal mit ein bisschen mehr "Luft" (Margins-Like) zwischen den einzelnen Elementen zeichnen lassen.

Schade das der TE sich noch nicht geäußert hat ob das Thema erledigt ist.

Ps: Mtcl sagt mir gerade noch nichts, werde ich nun nachholen!
Angehängte Dateien
Dateityp: 7z SplashBarThread.7z (850,5 KB, 19x aufgerufen)
Gruß vom KodeZwerg

Geändert von KodeZwerg (27. Jul 2020 um 10:21 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 6 von 6   « Erste     456   


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:45 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz