Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Update des Fensters für eine Zeit unterbinden (https://www.delphipraxis.net/168367-update-des-fensters-fuer-eine-zeit-unterbinden.html)

loirad 17. Mai 2012 15:17

Update des Fensters für eine Zeit unterbinden
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo liebe Delphi-PRAXIS'ler,

ich möchte einen Kalender programmieren. Für die einzelnen Tage nutze ich Listboxen in einer Stringgrid integriert.
Nun mein Problem: Beim Erzeugen bzw. Wechseln der Monate flackert das Formular sehr!

Wie könnte ich das beheben? Meine Idee: Update des Fensters für eine Zeit unterbinden. Wie geht das?

Liebe Grüße
loirad

Dalai 17. Mai 2012 15:24

AW: Update des Fensters für eine Zeit unterbinden
 
Ohne jetzt erst das Archiv runterladen zu müssen: TListBox.BeginUpdate und .EndUpdate benutzt?

MfG Dalai

loirad 17. Mai 2012 15:27

AW: Update des Fensters für eine Zeit unterbinden
 
Bei der Listbox gibt es kein .BeginUpdate oder .EndUpdate!
Oder habe ich etwas übersehen :oops:?

Dalai 17. Mai 2012 15:35

AW: Update des Fensters für eine Zeit unterbinden
 
Sorry, hab ich vertan. TListItems.BeginUpdate ist richtig. Aber selbst mit dem Hinweis hättest du etwas gefunden. TListItems ist übrigens eine Eigenschaft von TListBox.

MfG Dalai

Zacherl 17. Mai 2012 15:39

AW: Update des Fensters für eine Zeit unterbinden
 
Die Eigenschaft TListItems wäre mir jetzt nicht bekannt und aufgrund des vorranstehenden "T"s, handelt es sich hierbei auch eher um eine Klasse. Zum Hinzufügen mehrerer Items in einer ListBox geht man normalerweise wie folgt vor:

Delphi-Quellcode:
begin
  ListBox1.Items.BeginUpdate;
  try
    for i := 0 to 100000 do
    begin
      ListBox1.Items.Add('Ich bin Item Nummer ' + IntToStr(i));
    end;
  finally
    ListBox1.Items.EndUpdate;
  end;

loirad 17. Mai 2012 15:43

AW: Update des Fensters für eine Zeit unterbinden
 
Liste der Anhänge anzeigen (Anzahl: 1)
Da fliegt mir ne Exception um die Ohren, wenn ich es so mache:
Delphi-Quellcode:
for i:=0 to length(Tage)-1 do
  begin
   [B]Tage[i].Items.BeginUpdate;[/B]
   Tage[i]:=TListbox.Create(Kalender);
   Tage[i].Parent:=Kalender;
   Tage[i].Width:=Kalender.DefaultColWidth;
   Tage[i].Height:=Kalender.DefaultRowHeight;
   Tage[i].Left:=((i+Wochentag-1) mod 7)*(Kalender.DefaultColWidth+1);
   Tage[i].Top:=((i+Wochentag-1) div 7)*(Kalender.DefaultRowHeight+1)+40;
   Tage[i].Style:=lbOwnerDrawFixed;
   Tage[i].Font.Size:=10;
   Tage[i].Items.Add(Zentriere(inttostr(i+1)+'.'+inttostr(m)+'.'+inttostr(y),Tage[i].ClientWidth,
   Tage[i].Font));
   [B]Tage[i].Items.EndUpdate;[/B]
  end;
Tage ist ein array of TListBox!

Vielen Dank für weitere und gegebene Lösungen:thumb:

PS.: Bei der Lösung von Zacherl fliegt die gleiche Exception!

Zacherl 17. Mai 2012 15:48

AW: Update des Fensters für eine Zeit unterbinden
 
Du rufst BeginUpdate auf, bevor du die ListBox mit Create erstellt hast.

Aber in dem Falle ist BeginUpdate und EndUpdate wohl auch nicht das Problem, da du jeweils nur ein Item hinzufügst. Dafür erstellst du halt einen Haufen von ListBoxen. Eventuell solltest du dich mal nach einer anderen Komponente umschauen, die für eine Kalenderdarstellung eventuell besser geeignet ist.
Ansonsten probier mal die DoubleBuffered Eigenschaft des Formulars zu aktivieren.

loirad 17. Mai 2012 15:53

AW: Update des Fensters für eine Zeit unterbinden
 
Vielen Dank für den Tip - hätte ich auch selbst drauf kommen können :oops:!
Es flackert aber immernoch, wie du schon meintest. Doublebuffered ist schon an!

Ich müsste das Formular bzw. die Anzeige künstlich für diese Zeit einfrieren. Geht das irgendwie?

daywalker9 17. Mai 2012 16:03

AW: Update des Fensters für eine Zeit unterbinden
 
Du kannst WM_SETREDRAW nutzen. Beispiel findest Du dort: StackOverflow

loirad 17. Mai 2012 16:24

AW: Update des Fensters für eine Zeit unterbinden
 
Liste der Anhänge anzeigen (Anzahl: 2)
Hallo, Danke für deine Idee daywalker9, aber es funktioniert immmernoch nicht.
Es flackert zwar nicht, aber es erzeugt auch nichts (siehe Bild im Anhang).
Delphi-Quellcode:
for i:=0 to length(Tage)-1 do
  begin
   Tage[i]:=TListbox.Create(Kalender);
   Tage[i].Parent:=Kalender;
   SendMessage(Handle, WM_SETREDRAW, WPARAM(False), 0);
   try
   Tage[i].Width:=Kalender.DefaultColWidth;
   Tage[i].Height:=Kalender.DefaultRowHeight;
   Tage[i].Left:=((i+Wochentag-1) mod 7)*(Kalender.DefaultColWidth+1);
   Tage[i].Top:=((i+Wochentag-1) div 7)*(Kalender.DefaultRowHeight+1)+40;
   Tage[i].Style:=lbOwnerDrawFixed;
   Tage[i].Font.Size:=10;
   Tage[i].Items.Add(Zentriere(inttostr(i+1)+'.'+inttostr(m)+'.'+inttostr(y),Tage[i].ClientWidth,Tage[i].Font));
   finally
   SendMessage(Handle, WM_SETREDRAW, WPARAM(True), 0);
   end;
  end;
Eigentlich sieht es wie auf dem 2. Bild aus!

Hat noch jemand eine weitere Idee oder habe ich etwas übersehen? Danke für weitere Antworten:thumb:

Dalai 17. Mai 2012 16:32

AW: Update des Fensters für eine Zeit unterbinden
 
Zitat:

Zitat von Zacherl (Beitrag 1166943)
Die Eigenschaft TListItems wäre mir jetzt nicht bekannt und aufgrund des vorranstehenden "T"s, handelt es sich hierbei auch eher um eine Klasse.

OK, es war vielleicht nicht ganz korrekt formuliert, da die Eigenschaft Items heißt, aber dennoch ist diese Eigenschaft vom Typ TListItems und diese Klasse hat die Methoden BeginUpdate und EndUpdate.

MfG Dalai

daywalker9 17. Mai 2012 16:35

AW: Update des Fensters für eine Zeit unterbinden
 
Zitat:

Zitat von loirad (Beitrag 1166954)

Hat noch jemand eine weitere Idee oder habe ich etwas übersehen? Danke für weitere Antworten:thumb:

Du musst noch
Delphi-Quellcode:
Invalidate
oder
Delphi-Quellcode:
RedrawWindow(Handle, nil, 0, RDW_ERASE or RDW_FRAME or RDW_INVALIDATE or RDW_ALLCHILDREN)
aufrufen

Dalai 17. Mai 2012 16:37

AW: Update des Fensters für eine Zeit unterbinden
 
@loirad: Warum erstellst du nicht eine ListBox, die du je nach Auswahl mit anderen Daten füllst? Ich könnte ja noch nachvollziehen, dass es evtl, einfacher ist, für jeden Monat eine ListBox zu erzeugen, aber für jeden Tag eine?! Das verstehe ich nicht.

Ach, noch etwas, das WM_SETREDRAW wird - so meine Vermutung - nur das Neuzeichnen ein-/ausschalten, aber nicht das Neuzeichnen selbst auslösen/ausführen. Daher musst du wohl nach dem Reaktivieren ein Update/Repaint/Refresh/Invalidate auslösen.

MfG Dalai

jaenicke 17. Mai 2012 16:39

AW: Update des Fensters für eine Zeit unterbinden
 
Am wichtigsten wäre erst einmal beim Formular und den anderen Komponenten DoubleBuffered auf True zu setzen. Das reduziert das Flackern etwas.

Zudem sieht es so aus, als ob du jedesmal alle Komponenten neu erzeugst. :shock: Das macht keinen Sinn. Wenn du schon so viele Komponenten benutzt, dann solltest du sie zumindest wiederverwenden.

Und die sinnvollste Variante ist, dass du gar nicht erst so viele einzelne Komponenten benutzt. Ein Beispiel findest du z.B. hier:
http://www.delphipraxis.net/132375-p...-beta-6-a.html
Das ist ein Periodensystem und zwar nicht ganz das selbe, aber vom Prinzip her genau was du machen kannst. Einfach den Inhalt selbst zeichnen und auf einer TPaintBox darstellen.

loirad 17. Mai 2012 16:44

AW: Update des Fensters für eine Zeit unterbinden
 
Zitat:

Zitat von daywalker9 (Beitrag 1166959)
Du musst noch
Delphi-Quellcode:
Invalidate
oder
Delphi-Quellcode:
RedrawWindow(Handle, nil, 0, RDW_ERASE or RDW_FRAME or RDW_INVALIDATE or RDW_ALLCHILDREN)
aufrufen

So:
Delphi-Quellcode:
 for i:=0 to length(Tage)-1 do
  begin
   Tage[i]:=TListbox.Create(Kalender);
   Tage[i].Parent:=Kalender;
   SendMessage(Handle, WM_SETREDRAW, WPARAM(False), 0);
   try
   Tage[i].Width:=Kalender.DefaultColWidth;
   Tage[i].Height:=Kalender.DefaultRowHeight;
   Tage[i].Left:=((i+Wochentag-1) mod 7)*(Kalender.DefaultColWidth+1);
   Tage[i].Top:=((i+Wochentag-1) div 7)*(Kalender.DefaultRowHeight+1)+40;
   Tage[i].Style:=lbOwnerDrawFixed;
   Tage[i].Font.Size:=10;
   Tage[i].Items.Add(Zentriere(inttostr(i+1)+'.'+inttostr(m)+'.'+inttostr(y),Tage[i].ClientWidth,Tage[i].Font));
   finally
   SendMessage(Handle, WM_SETREDRAW, WPARAM(True), 0);
   RedrawWindow(Handle, nil, 0, RDW_ERASE or RDW_FRAME or RDW_INVALIDATE or RDW_ALLCHILDREN);
   end;
  end;
geht es leider auch nicht - ist eine Mischung aus flackern und nicht zeichnen :arrow: es ist das gleiche Bild wie bei meinem vorherigen Post, nur das es noch flackert!

Liebe Grüße
loirad

PS.:
Es steht im OnPaint drin - liegt da der Fehler?
@Dalai: Ich möchte eine Gesamtübersicht über den Monat mit To-Do's haben!
@jaenicke: DoubleBuffered ist an (hatte ich schon erwähnt)! Mit dem neuen Erzeugen macht es sich am einfachsten!

daywalker9 17. Mai 2012 16:46

AW: Update des Fensters für eine Zeit unterbinden
 
Mach das setzen des WM_SETREDRAW und RedrawWindow nicht innerhalb der schleife, sondern vorher bzw nachher

loirad 17. Mai 2012 16:48

AW: Update des Fensters für eine Zeit unterbinden
 
@daywalker9: macht keinen Unterschied!

Hat jemand eine andere Lösung?

jaenicke 17. Mai 2012 16:51

AW: Update des Fensters für eine Zeit unterbinden
 
Oh, das mit dem DoubleBuffered hatte ich übersehen.

Zitat:

Zitat von loirad (Beitrag 1166964)
Mit dem neuen Erzeugen macht es sich am einfachsten!

Erstens kommt dir das nur so vor, zweitens musst du eben selbst entscheiden was du willst:
Eine gute Lösung oder eine, die dir einfach erscheint, aber dafür eben deutliche Schwächen hat... Viel verbessern lässt sich da nicht... Das ist so schlicht nicht vorgesehen.

Klar, selbst zeichnen ist schwerer, aber dafür am Ende auch viel besser vom Ergebnis her.

Aber schon das Wiederverwenden bringt viel und ist eher einfacher als deine jetzige Lösung...

daywalker9 17. Mai 2012 16:55

AW: Update des Fensters für eine Zeit unterbinden
 
Zitat:

Zitat von loirad (Beitrag 1166969)
@daywalker9: macht keinen Unterschied!

Hat jemand eine andere Lösung?

Ersetze mal SendMEssage durch
Delphi-Quellcode:
 Self.Perform(WM_SETREDRAW, WPARAM(false), 0);

loirad 17. Mai 2012 17:08

AW: Update des Fensters für eine Zeit unterbinden
 
@jaenicke: Es flackert immernoch und dazu noch irgendwelche Exceptions (das liegt aber wahrscheinlich an mir)!
@daywalker9: Gleiches Resultat! Liegt es daran, dass es im OnPaint ist und damit eine Endlosschleife erzeugt?

daywalker9 17. Mai 2012 17:13

AW: Update des Fensters für eine Zeit unterbinden
 
Im OnPaint?

Du erzeugst bei jedem Malen der Form die ListBoxen erneut? Dann ist es klar, das es flackert, reicht es nicht im FormCreate?

loirad 17. Mai 2012 17:57

AW: Update des Fensters für eine Zeit unterbinden
 
Nein, da es Maximiert gestartet wird und im OnCreate dabei noch nicht die richtige Größe hat - ich werde es mal außerhalb des OnPaint versuchen!
Geht doch!
Super!
Danke @all!!!

Auch für die Antworten die nicht funktioniert haben!!!

Vielen Dank - ich liebe die DP-Community -> Sehr schnelle Hilfe!


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:19 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz