Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi TTreeView wird durch TActionMainMenuBar deutlich langsamer (https://www.delphipraxis.net/200192-ttreeview-wird-durch-tactionmainmenubar-deutlich-langsamer.html)

BerndS 27. Mär 2019 14:52

TTreeView wird durch TActionMainMenuBar deutlich langsamer
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,
mir ist aufgefallen dass das Füllen einer TTreeView Komponente bei mir ca. um den Faktor 6-7 langsamer wird, sobald im Projekt oder Formular ein Menü vom Typ TActionMainMenuBar verwendet wird und diese sichtbar ist.:?

Bemerkt habe ich es, da der gleiche Dialog in verschiedenen Programmen mal schnell und mal langsam den Baum aufgebaut wurde.
Meine Suche nach der Ursache ist leider erfolglos geblieben.

Ich habe mal ein Miniprojekt angehängt.
Zum Test:
1. Schalter Treeview füllen drücken
2. mit ActionMainMenuBar aktivieren
3. Schalter Treeview füllen drücken
Danach sollte das Label das Ergebnis anzeigen.

Vielleicht hat ja jemand eine Erklärung für den Zeitunterschied.
Gruß Bernd

freejay 27. Mär 2019 16:14

AW: TTreeView wird durch TActionMainMenuBar deutlich langsamer
 
Sehr interessanter Effekt.

Keine Ahnung, wo das herkommen kann.

Eigentlich kann ich mir nur vorstellen, dass die ActionMainMenuBar beim Hören auf die Windows-Botschaften eine Verzögerung erzeugt:

Delphi-Quellcode:
    procedure CMEnabledchanged(var Message: TMessage); message CM_ENABLEDCHANGED;
    procedure CMWininichange(var Message: TWMWinIniChange); message CM_WININICHANGE;
    procedure WMKeyDown(var Message: TWMKeyDown); message WM_KEYDOWN;
    procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST;
    procedure WMSysCommand(var Message: TWMSysCommand); message WM_SYSCOMMAND;
    procedure WMSysKeyDown(var Message: TWMSysKeyDown); message WM_SYSKEYDOWN;
    procedure WMSysKeyUp(var Message: TWMSysKeyUp); message WM_SYSKEYUP;
    function MainWndHook(var Message: TMessage): Boolean;
Dann müsste aber vermutlich der/die TreeView beim Befüllen intern auch Botschaften verwenden, sonst könnte die MenüBar ja nicht dazwischenfunken...

TurboMagic 27. Mär 2019 17:39

AW: TTreeView wird durch TActionMainMenuBar deutlich langsamer
 
Da es eine Demo von dir gibt könntes du dieses Problem auch gerne in quality.embarcadero.com einstellen und dann die Report Nummer hier posten.

BerndS 28. Mär 2019 07:26

AW: TTreeView wird durch TActionMainMenuBar deutlich langsamer
 
Ich habe die Hooks noch mal genauer angeschaut. Die Verzögerung wird in der Vcl.ActnMenus durch TMenuList.Notify durch CallWindowHook ausgelöst sobald das erste Menü dort eingefügt wird.

Auf die schnelle habe ich die Unit Vcl.ActnMenus um die procedure EnableDisableMenuListHooks erweitert.
Delphi-Quellcode:
procedure EnableDisableMenuListHooks(AEnable: Boolean);
begin
  if Assigned(MenuList) and (MenuList.Count > 0) then
    if AEnable then
    begin
      if MenuCallWndHook = 0 then
      MenuCallWndHook := SetWindowsHookEx(WH_CALLWNDPROC,
        {$IFNDEF CLR}@{$ENDIF}CallWindowHook, 0, GetCurrentThreadID);
    end
    else
      if (MenuCallWndHook <> 0) then
      begin
        UnHookWindowsHookEx(MenuCallWndHook);
        MenuCallWndHook := 0;
      end;
end;
Diese rufe ich dann hier auf und die Verzögerungen sind weg (Ohne Debugger).:-D
Delphi-Quellcode:
procedure TfmTestTreeview.btClick(Sender: TObject);
  procedure AddNodes(ACount, NL: Integer; ANode: TTreeNode);
  var
    N: TTreeNode;
    I: Integer;
    S: string;
  begin
    for I := 1 to ACount do
    begin
      if Assigned(ANode) then
      begin
        N := tv.Items.AddChild(ANode, 'Node ' + NL.ToString + '.' + I.ToString);
        if N.Level < 3 then
          AddNodes(10, I, N)
        else
          Break;
      end
      else
      begin
        N := tv.Items.Add(nil, 'Node ' + I.ToString);
        AddNodes(10, I, N);
      end;
    end;
  end;

var
  TC: Cardinal;
  E: Extended;
begin
  tv.Items.Clear;
  EnableDisableMenuListHooks(False);
  try
    tv.Items.BeginUpdate;
    try
      bt.Enabled := False;
      TC := GetTickCount;
      AddNodes(20, 0, nil);
      TC := GetTickCount - TC;
      if cbAMMB.Checked then
        FTCM := TC
      else
        FTC := TC;
      lTC.Caption := TC.ToString + ' ticks';
      if (FTC > 0) and (FTCM > 0) then
      begin
        E := FTCM / FTC;
        lTC.Caption := lTC.Caption + ' ( ohne ' + FTC.ToString + ' ticks ' + FloatToStr(RoundTo(E, - 1)) + ' x langsamer)';
      end;
    finally
      tv.Items.EndUpdate;
      bt.Enabled := True;
    end;
  finally
    EnableDisableMenuListHooks(True);
  end;
end;

TurboMagic 28. Mär 2019 16:48

AW: TTreeView wird durch TActionMainMenuBar deutlich langsamer
 
Bitte Problem samt Lösungsansatz inQP erfassen, damit hoffentlich alle in einer zukünftigen Version von einem offiziellen Bugfix profitieren. Danke!

BerndS 29. Mär 2019 07:59

AW: TTreeView wird durch TActionMainMenuBar deutlich langsamer
 
Leider sind meine Englisch Kenntnisse nicht die besten.:? Mein Lösung ist auch nicht optimal, da es nicht automatisch geht.
Aber ich werde mal versuchen meinen ersten QP zu erstellen.

BerndS 29. Mär 2019 13:10

AW: TTreeView wird durch TActionMainMenuBar deutlich langsamer
 
Ich habe es mit Googles Hilfe in QP hinzugefügt. RSP-24106

TurboMagic 29. Mär 2019 14:49

AW: TTreeView wird durch TActionMainMenuBar deutlich langsamer
 
Danke. Habe dafür gestimmt.


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:41 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