![]() |
Visible-Status von TShape in Timer-Callback Funktion ändern
Liste der Anhänge anzeigen (Anzahl: 1)
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; |
AW: Visible-Status von TShape in Timer-Callback Funktion ändern
Zitat:
Delphi-Quellcode:
(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
Delphi-Quellcode:
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. |
AW: Visible-Status von TShape in Timer-Callback Funktion ändern
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?
|
AW: Visible-Status von TShape in Timer-Callback Funktion ändern
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... |
AW: Visible-Status von TShape in Timer-Callback Funktion ändern
Zitat:
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
Delphi-Quellcode:
schreibt einfach blind den Typ der Variable um (prüft nicht den Inhalt)
TIrgendwas(etwas)
weicher Cast
Delphi-Quellcode:
prüft ob wirklich der Typ drin ist
(etwas as TIrgendwas)
|
AW: Visible-Status von TShape in Timer-Callback Funktion ändern
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; |
AW: Visible-Status von TShape in Timer-Callback Funktion ändern
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. |
AW: Visible-Status von TShape in Timer-Callback Funktion ändern
@Medium, vielen Dank! Ich benutze ein CreateTimerQueue- und Timer-Objekt von
![]() 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! |
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:37 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