AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein GUI-Design mit VCL / FireMonkey / Common Controls Delphi Visible-Status von TShape in Timer-Callback Funktion ändern
Thema durchsuchen
Ansicht
Themen-Optionen

Visible-Status von TShape in Timer-Callback Funktion ändern

Ein Thema von palmakunkel · begonnen am 22. Aug 2022 · letzter Beitrag vom 24. Aug 2022
Antwort Antwort
palmakunkel

Registriert seit: 3. Dez 2005
Ort: Coswig
13 Beiträge
 
Delphi 11 Alexandria
 
#1

Visible-Status von TShape in Timer-Callback Funktion ändern

  Alt 22. Aug 2022, 17:25
Eine von TShape abgeleitete Metronom-Komponente, deren Visible-Status sich im Rhythmus ändert. Das soll über die Timer-Callback-Funktion erfolgen (Win-API). Diese bekommt aSender übergegen. Wenn ich in der Funktion auf TShape(aSender).Visible zugreife gibt es einen Fehler. Wahrscheinlich ist das für den Profi banal, aber ich bin Autodidakt und hier an meiner Wissensgrenze. Kann mir jemand einen Tipp geben?

type
TMetronom = class(TShape)
private
{ Private-Deklarationen }
fBlinkDuration: integer;
fEnabled: boolean;
fTimerQueue: TgoTimerQueue;
...
procedure OnTimer(const ASender: TObject);
public
constructor Create(aOwner: TComponent); override;
destructor Destroy; override;
...
published
property BlinkDuration: integer read fBlinkDuration write fBlinkDuration;
end;

implementation

constructor TMetronom.Create(AOwner: TComponent);
begin
inherited create(AOwner);
...
FTimerQueue := TgoTimerQueue.Create;
...
end;

procedure TMetronom.OnTimer(const ASender: TObject);
begin
if fEnabled then
begin
TShape(aSender).Visible:=false;
Sleep(BlinkDuration);
TShape(aSender).Visible:=true;
end;
end;
Angehängte Dateien
Dateityp: zip MetroGD3.zip (987 Bytes, 1x aufgerufen)
Gunter Dickopf
sie passten gut zueinander - geometrisch gesehen
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: Visible-Status von TShape in Timer-Callback Funktion ändern

  Alt 22. Aug 2022, 18:10
Zitat:
TShape(aSender).Visible
(aSender as TShape).Visible

Und dann überleg dir, warum es nun den "richtigen" Fehler gibt, bzw. warum er dort auftritt.




Warum die Variable fEnabled, anstatt direkt das Enabled des Timers durchzureichen?
Außerdem läuft der Timmer sinnlos auch dann, wenn nichts gemacht wird.

Und Sleep ... NEIN.
Da fehlt zwischendurch das Repaint und außerdem hängt dabei die Anwendung.
Lösung: Timer mit halbem Interval und dann Visible := not Visible;



PS: [DELPHI] ... [/DELPHI]



Statt die Komponente ständig sichtbar/unsichtbar zu machen, würde ich eher empfehlen z.B. eine TPaintBox zu nehmen und nur deine Komponente im Interval neu zu zeichnen,
anstatt die halbe Form (mindestens den Parent) zu zwingen sich neu zu zeichnen, wenn deine Komponente unsichtbar wird.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu (22. Aug 2022 um 18:21 Uhr)
  Mit Zitat antworten Zitat
palmakunkel

Registriert seit: 3. Dez 2005
Ort: Coswig
13 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Visible-Status von TShape in Timer-Callback Funktion ändern

  Alt 23. Aug 2022, 11:23
sehr wertvolle Hinweise, danke! Besonders den mit TPaintBox will ich einarbeiten. Aber (aSender as TShape).Visible erzeugt den gleichen Fehler, wie TShape(aSender).Visible. Ich nehme aber nicht TTimer, der ist zu ungenau, sonder die API Funktionen CreateTimerQueueTimer() nach Anlegen der Queue. Da kommt die Callback-Funktion mit dem übergebenen Zeiger nicht klar. Der zeigt offenbar nicht auf TShape, sondern ins Nirvana, oder?
Gunter Dickopf
sie passten gut zueinander - geometrisch gesehen
  Mit Zitat antworten Zitat
TurboMagic

Registriert seit: 28. Feb 2016
Ort: Nordost Baden-Württemberg
2.824 Beiträge
 
Delphi 12 Athens
 
#4

AW: Visible-Status von TShape in Timer-Callback Funktion ändern

  Alt 23. Aug 2022, 11:55
Vermutlich zeigt der auf fTimerQueue.
Kannst ja mal die Adressen vom Sender und dem Feld vergleichen...
Im OnTimer vom TTimer ist das Übergebene Sender Objekt ja auch das des Timers selber...
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: Visible-Status von TShape in Timer-Callback Funktion ändern

  Alt 23. Aug 2022, 12:26
Zitat:
Aber (aSender as TShape).Visible erzeugt den gleichen Fehler
Dürfte es eigentlich nicht.

Jetzt müsste ein Cast-Error kommen, weil ASender bestimmt der Timer ist und nicht das Shape,

aber da du eh bereits in einer Methode dieses TShape/TMetronom bist, brauchst du Sender garnicht. (Self reicht)



harter Cast TIrgendwas(etwas) schreibt einfach blind den Typ der Variable um (prüft nicht den Inhalt)
weicher Cast (etwas as TIrgendwas) prüft ob wirklich der Typ drin ist
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu (23. Aug 2022 um 12:31 Uhr)
  Mit Zitat antworten Zitat
palmakunkel

Registriert seit: 3. Dez 2005
Ort: Coswig
13 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: Visible-Status von TShape in Timer-Callback Funktion ändern

  Alt 23. Aug 2022, 16:47
wenn in OnTimer ein Funktionsaufruf zum Umfärben der Canvas steht klappt es, wenn ich dort direkt Canvas.FillRect() aufrufe, gibt es Speicherfehler.
Die Sleep-Funktion ist sicher nicht die hohe Schule, aber da das Programm, in dem das Metronom läuft, nur Noten anzeigt, also praktisch nichts zu tun hat, stört das 50 ms-Schlafen eigentlich nicht. Wenn ich die Farbe rhythmisch wechsele mit doppelter Timer-Geschwindigkeit, sind die grau- und rot-Phasen gleich lang, so habe ich praktisch nur einen "Grau-Blitz" in einer roten Fläche.

Vielen Dank nochmal für die Tipps und die schnellen Reaktionen!

procedure TMetronom1.FillColorRed;
begin
Canvas.Brush.Color:=clRed;
Canvas.FillRect(ClientRect);
end;

procedure TMetronom1.FillColorBtnFace;
begin
Canvas.Brush.Color:=clBtnFace;
Canvas.FillRect(ClientRect);
end;

procedure TMetronom1.OnTimer(const ASender: TObject);
begin
FillColorBtnFace;
Sleep(BlinkDuration);
FillColorRed;
end;
Gunter Dickopf
sie passten gut zueinander - geometrisch gesehen
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.679 Beiträge
 
Delphi 2007 Enterprise
 
#7

AW: Visible-Status von TShape in Timer-Callback Funktion ändern

  Alt 23. Aug 2022, 18:34
Wenn du im Parameter "Parameter" von CreateTimerQueueTimer() dein TShape übergibst, sollte der gleichnamige Parameter der Callback-Funktion exakt denselben Wert enthalten. Ein PVOID wird vermutlich als "Pointer" übersetzt, also bloß einfach ein typfreier Wert.

Wie übergibst du denn dein Shape beim Aufruf von CreateTimerQueueTimer? Ich meine, dass es einen Unterschied macht, ob man "@MyShape" oder "Pointer(MyShape)" benutzt. Versuche mal das jeweils andere von dem was du bisher hattest.

Im Callback selbst sollte dann ein (lpParameter as TShape).Visible eigentlich gehen, es sei denn du zerstörtst das Shape zwischendurch und erstellst es neu. Dann ist der alte Pointer natürlich (höchstwahrscheinlich) ungültig.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
palmakunkel

Registriert seit: 3. Dez 2005
Ort: Coswig
13 Beiträge
 
Delphi 11 Alexandria
 
#8

AW: Visible-Status von TShape in Timer-Callback Funktion ändern

  Alt 24. Aug 2022, 09:07
@Medium, vielen Dank! Ich benutze ein CreateTimerQueue- und Timer-Objekt von https://github.com/grijjy/DelphiTimerQueue. Das funktioniert auch gut. Dass der Callback-Funktion die Adresse des Timer-Objektes übergeben wird und nicht die vom TShape hatte ich bisher nicht kapiert.
Ich hatte eine Variante, in der ich in das Timer-Objekt fShapeAddr eingefügt habe, in der Initialisierung habe ich die TShape-Adresse da rein geladen und auf die in der Callback-Funktion zugegriffen. Das ging. Jetzt wollte ich aber ein Objekt machen, in dem die Ausgabekomponente im Zentrum steht und nicht der Timer, und da ging der Schlamassel los. Aber jetzt funktioniert es. Vielen Dank nochmal an die Mitdenker!
Gunter Dickopf
sie passten gut zueinander - geometrisch gesehen
  Mit Zitat antworten Zitat
Antwort Antwort

 

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 20:27 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