![]() |
Komponente umstellen
Ich möchte die TAudioVolume Komponente umstellen.
Delphi-Quellcode:
TAudioVolume = class(TCustomControl)
protected procedure CreateWnd; override; ....
Delphi-Quellcode:
Später sollen auf diesen Panel die ProgressBars kommen.
procedure TAudioVolume.CreateWnd;
var FPanel: TPanel; begin inherited; Width := 100; Height := 100; FPanel := TPanel.Create(Owner); FPanel.Parent := self; self.Owner.InsertComponent(FPanel); FPanel.Left := 5; FPanel.Top := 5; FPanel.Width := Width - 10; FPanel.Height := Height - 10; end; Mein Problem ist nun wenn ich die Komponente auf die Form klatsche dann kann ich die Eigenschaften des Panels ändern.. Das will ich aber nicht. Was läuft falsch? Siehe Shot der seltsame eintrag für das Panel. Sorry wenn das dumm rüberkommt habe aber mit VCL Komponenten erstellen nicht so viel Erfahrung. gruss |
AW: Komponente umstellen
Warum fügst Du die Kompinenet dem Owner hinzu? Ist dann ja das Formular.
Delphi-Quellcode:
self.Owner.InsertComponent(FPanel);
|
AW: Komponente umstellen
Ich tät das so machen:
Delphi-Quellcode:
Ob's der Weißheit letzter Schluss ist, weiß ich aber nicht.
procedure TAudioVolume.CreateWnd;
var FPanel: TPanel; begin inherited; Width := 100; Height := 100; FPanel := TPanel.Create(self); FPanel.Parent := self; FPanel.Left := 5; FPanel.Top := 5; FPanel.Width := Width - 10; FPanel.Height := Height - 10; end; |
AW: Komponente umstellen
So hätte ich es auch gemacht, dann ist der Owner die eigene Komponenete und nicht der Owner der Komponente.
|
AW: Komponente umstellen
Zitat:
PS: Ok! Funktioniert jetzt Danke euch .. War wohl ein Denkfehler. gruss |
AW: Komponente umstellen
Noch ein kleines Problem.
Warum werden die property zu spät ausgeführt?
Delphi-Quellcode:
Ich addiere ne neue Komponente zur Form
private
FAppVolume: boolean; procedure SetAppVolume(Value: boolean); published property AppVolume: boolean read FAppVolume write SetAppVolume; procedure TAudioVolume.SetAppVolume(Value: boolean); begin if Value = FAppVolume then exit; FAppVolume := Value; end; Anschließend ändere ich die Eigenschaft von AppVolume auf True. Die Eigenschaft wird aber nicht direkt ausgeführt.
Delphi-Quellcode:
Bei der 5 Komponente wo die Eigenschaft auf True steht springt sie trotzdem in SetComponents hinein.
constructor TAudioVolume.Create(AOwner: TComponent);
var HR: HResult; N: Cardinal; MyRegistry: TRegistry; ISessionEvents: TAudioSessionEvents; IAudioEndpointEvents: TAudioEndpointEvents; begin inherited Create(AOwner); if not FAppVolume then SetComponents; Erst danach wird erkannt das FAppVolume eigentlich True ist. Wie kann ich das erzwingen. gruss |
AW: Komponente umstellen
Im Kontruktor haben die privaten Felder noch die Standard-Werte (0-Entsprechung, also 0, '', nil, false, je nach Datentyp). Deshalb wird Deine Abfrage immer true ergeben, da die Eigenschaften ja erst später gesetzt werden, da ist der Konstruktor aber längst abgearbeitet.
|
AW: Komponente umstellen
Zitat:
Traurig das ganze das man in der Design Umgebung nicht reale Werte anzeigen kann. Seltsam nur wenn ich eine Checkbox nehme und hier die Eigenschaft Checked = True einstelle (im Designer) Funktioniert es doch auch. Warum dann nicht in eigenen Komponenten. Ist doch eigentlich das gleiche. Oder meinst du ich soll das aus Create herausnehmen?
Delphi-Quellcode:
und an passender stelle unterbringen?
if not FAppVolume then
SetComponents; Die frage wäre dann wo? Da diese sich ja beim erstellen ändern sollen nachdem sie auf die Form gelegt wurden. Siehe Shot Designer soll gleich sein wie Laufzeit. gruss |
AW: Komponente umstellen
Im Kontruktor jedenfalls bringt es Dir nichts. Wäre der sowieso schon vorhandene Setter nicht besser geeignet?
|
AW: Komponente umstellen
Zitat:
gruss |
AW: Komponente umstellen
Delphi-Quellcode:
oder so ähnlich. AfterConstruction wäre auch noch eine Möglichkeit, aber das wird IIRC nicht immer ausgeführt (es sei denn, ich werfe da gerade etwas durcheinander).
procedure TAudioVolume.SetAppVolume(Value: boolean);
begin if Value = FAppVolume then exit; FAppVolume := Value; if not FAppVolume then SetComponents; end; |
AW: Komponente umstellen
Zitat:
Ich komme zu spät in den Setter das ist ja mein Problem.
Delphi-Quellcode:
Ich bekomme erst ein True nachdem ich Create hinter mir gelassen habe.
procedure TAudioVolume.SetAppVolume(Value: boolean);
begin if Value = FAppVolume then exit; FAppVolume := Value; if FAppVolume then begin FGroupBox.Caption := 'Application'; pbAppMeter := TProgressBar.Create(self); pbAppMeter.Parent := FGroupBox.Parent; pbAppMeter.Orientation := pbVertical; pbAppMeter.Max := 100; pbAppMeter.Min := 0; pbAppMeter.Smooth := true; lblAppPeak := TLabel.Create(self); lblAppPeak.Parent := FGroupBox.Parent; lblAppPeak.Caption := 'M'; pbAppMeterL := TProgressBar.Create(self); pbAppMeterL.Parent := FGroupBox.Parent; pbAppMeterL.Orientation := pbVertical; pbAppMeterL.Max := 100; pbAppMeterL.Min := 0; pbAppMeterL.Smooth := true; lblAppPeakL := TLabel.Create(self); lblAppPeakL.Parent := FGroupBox.Parent; lblAppPeakL.Caption := 'L'; tbAppVolume := TTrackBar.Create(self); tbAppVolume.Parent := FGroupBox.Parent; tbAppVolume.Orientation := trVertical; tbAppVolume.Max := 32; tbAppVolume.Min := 0; tbAppVolume.TickStyle := tsAuto; tbAppVolume.Frequency := 3; tbAppVolume.Position := 0; cbAppMute := TCheckbox.Create(self); cbAppMute.Parent := FGroupBox.Parent; cbAppMute.Caption := 'Mute'; pbAppMeterR := TProgressBar.Create(self); pbAppMeterR.Parent := FGroupBox.Parent; pbAppMeterR.Orientation := pbVertical; pbAppMeterR.Max := 100; pbAppMeterR.Min := 0; pbAppMeterR.Smooth := true; lblAppPeakR := TLabel.Create(self); lblAppPeakR.Parent := FGroupBox.Parent; lblAppPeakR.Caption := 'R'; tbAppVolume.Position := round((1.0 - GetVolume) * tbAppVolume.Max); tbAppVolume.OnChange := tbAppVolumeChange; cbAppMute.Checked := IsMuted; cbAppMute.OnClick := cbAppMuteClick; PostMessage(Handle, WM_SIZE, 0, 0); end; end; Das ist aber zu spät. Angenommen das Teil liegt schon auf der Form und ich ändere dann den Status über die Property AppVolume dann müsste sich die Componente anhand der im Setter eingestellten werte ändern. Tut es aber nicht so wie es soll. gruss |
AW: Komponente umstellen
In den Setter kommst Du, sobald der Wert der Property gesetzt wird. Ob aus dem Objektinspektor heraus oder per Code ist dabei egal, außer dass beim Objektinspektor der ComponentState auch csDesigning enthält, falls Dir das etwas nützt.
|
AW: Komponente umstellen
Er springt nicht in den Setter im Design mode so das ich testen kann woran das liegt.
Also wenn ich die property im Objektinspektor ändere. gruss |
AW: Komponente umstellen
Hast Du das Package auch neu installiert?
|
AW: Komponente umstellen
Zitat:
Der Vorgang ist wie folgt. Addiere ich die Komponente dann ist alles in Ordnung. Schalte ich jetzt um also auf AppVolume dann ändert sich das Aussehen entsprechend und ist auch in Ordnung Das selbe spiel zurück das ist auch in Ordnung. Schließe ich die Form und öffne diese anschließend wieder dann ist alles Durcheinander. So als wenn die Property nicht gespeichert würde. Es geht um die Ansicht im Designer :) gruss |
AW: Komponente umstellen
Dafür ist soweit ich weiß
![]() |
AW: Komponente umstellen
Zitat:
Wenn du mal reinschauen willst kann ich es hochladen. gruss |
AW: Komponente umstellen
Leider funktioniert das mit den property im Designer nicht.
Habe es deshalb so geändert dass das Anwendungs Volumen (Ansicht) erst zur Laufzeit geändert wird. Dafür weise ich der AudioVolume5 einfach AppVolume zu.
Delphi-Quellcode:
AudioVolume5.AppVolume := True
Volumen 1 -> 4 werden dann für die Geräte verwendet wie auch immer.
Delphi-Quellcode:
Auch diese werden dann erst zur Laufzeit (Ansicht) geändert.
AudioVolume1.SelectAudioDevice(I);
AudioVolume2.SelectAudioDevice(1); AudioVolume3.SelectAudioDevice(2); AudioVolume4.SelectAudioDevice(3); gruss |
AW: Komponente umstellen
Es gibt noch die Methode Loaded, die nach dem Laden der Eigenschaften ausgeführt wird. Wenn man im Objektinspektor eingestellte Eigenschaften verwenden will ohne im Setter jedesmal etwas zu aktualisieren, kann man diese überschreiben. Dann sind alle Eigenschaften bereits gesetzt.
|
AW: Komponente umstellen
Zitat:
Habe noch ein anderes kleines Problem. Zur zeit setze ich die Device auf diese weise per Hand.
Delphi-Quellcode:
Das ist mir aber nicht aussagekräftig genug.
AudioVolume2.SelectAudioDevice(1);
Jetzt versuche ich die Device als Property zu addieren. So kann man sehen welche gerade aktiv sind. Allerdings hab ich da noch einen Fehler, es werden die TStrings addiert aber in einer Liste. Ich möchte die Einträge jedoch direkt wählen als Liste im AudioDevice property. Siehe Shot. gruss |
AW: Komponente umstellen
Wenn Du da im Objektinspektor was auswählen willst, nimm doch dafür 'nen Aufzählungstypen.
Sowas z. B.?
Delphi-Quellcode:
An die Nummer für
TAudioDevices = set of (adLautsprecher, adStereoMix, acLineIn, acCDAudio);
... FAudioDevices: TAudioDevices; ... property AudioDevices: TAudioDevices read FAudioDevices write FAudioDevices; // oder halt 'nen Setter bauen, wenn erforderlich...
Delphi-Quellcode:
müsstest Du dann in der Art kommen:
AudioVolume2.SelectAudioDevice(1)
Delphi-Quellcode:
Ord beginnt bei 0 zu zählen, eventuell müsste es dann
AudioVolume2.SelectAudioDevice(Ord(FAudioDevices))
Delphi-Quellcode:
heißen.
AudioVolume2.SelectAudioDevice(Ord(FAudioDevices) + 1)
|
AW: Komponente umstellen
Zitat:
Sind vom System zu System unterschiedlich. Ich möchte eine Liste im Objektinspektor wo ich das jeweilige Device auswählen und der Komponente zuweisen kann. Aktuell steht dort TStrings logisch weil die Rückgabe nun mal TStings ist. Also was zurückgeben damit die Einträge addiert werden.
Delphi-Quellcode:
function TAudioVolume.GetAudioDevice: TStrings;
var N: integer; FDeviceList: array of TDeviceInfo; Items: TStringList; begin Items := TStringList.Create; FAudioDevice := TStringList.Create; if FDeviceCount > 0 then begin SetLength(FDeviceList, FDeviceCount); for N := 0 to (FDeviceCount - 1) do begin FDeviceList[N] := GetDeviceInfo2(DeviceCollection, N); ExtractStrings(['('], [], pWideChar(FDeviceList[N].DeviceName), Items); FAudioDevice.Add(Items[0]); Items.Clear; end; Items.Free; end; Result := FAudioDevice; end; Zitat:
Nur diese muss ich dort erst mal addieren ;) arghhh VCL :) Komme langsam zum schluss das der Objekt Inspektor in Delphi Müll ist. Kann das sein? Bool werte werden zu spät ausgewertet, Listen kann man nicht addieren usw.. Selbst mit dem alten VB6 ist so was alles möglich. Kopfschütteln. gruss |
AW: Komponente umstellen
Ich kann Dir nicht so recht folgen, wo jetzt genau Deine Probleme liegen und warum Boolean-Werte zu spät ausgewertet werden.
Ist es so, dass zur Laufzeit alles funktioniert und auch wenn Du zur Designtime Deine Werte umstellst, aber wenn Du ein Projekt startest oder ein Formular öffnest funktioniert es nicht? In dem Fall müsstest Du nachvollziehen, wann welche Werte in die DFM geschrieben und daraus wieder gelesen werden. Also schau Dir evtl. mal die DFM im Textformat an, was dort eigentlich rein geschrieben wird oder wurde. Wenn die DFM-Informationen passen musst Du schauen, wie und wann diese wieder gelesen. |
AW: Komponente umstellen
Zitat:
Problem 1. Ich erstelle ein Property FAddVolume (Boolean). Wenn ich diesen Wert im Objektinspektor ändere funktioniert soweit alles aber sobald das Formular in Delphi geschlossen und anschließend wieder geöffnet wird ist alles durcheinander. Laufzeit ist Ok. Problem 2. Ich erstelle eine Liste der vorhandenen Device Diese wird im Objektinspektor als TStrings angezeigt und nicht als Liste so wie ich es gerne hätte. Einen anderen weg habe ich noch nicht gefunden. In der DFM wird alles richtig geschrieben. Zitat:
Beim direkten ändern nicht aber beim erneuten öffnen der Form. gruss |
AW: Komponente umstellen
Also zu 1) solltest Du den Hinweis von DeddyH nochmal berücksichtigen.
Wenn Dein Formular geöffnet wird (egal ob zur Designtime oder Runtime) werden zunächst die Komponenten erstellt und DANACH werden die Werte gesetzt. Wenn Du im Konstruktor auf bestimmte Werte prüfst, ist das einfach zu früh. Du musst entweder im Setter der Eigenschaft auf Änderungen reagieren (i.d.R. die sinnvollste Lösung) oder nach den DatenAusDerDFM-lesen (in Loaded). Zu 2) weiß ich auch nicht recht. Du willst zur Designtime einen Wert als Text festlegen - richtig? Aber auf jedem System, auf dem die EXE gestartet wird, können die möglichen Werte abweichen? Insofern wäre m.E. ein Property-Editor sinnvoll, der Dir die möglichen Werte auflistet und Du EINEN als String speicherst. Beim Programmstart wird geprüft, ob dieser Wert auf dem aktuellen System verfügbar ist und dann eingestellt. Wenn nicht wird ein Dialog für die Auswahl geöffnet. In der DFM würde dann nur ein String gespeichert werden. Für bearbeitbare Listen im Formular sind TCollection vorgesehen. |
AW: Komponente umstellen
Danke erst mal.
Zitat:
Das Problem ist nur ich benötige diese abfrage in create weil sonst die ganzen Componenten nicht erstellt werden. Das führt unweigerlich zu einem AV Zitat:
Das über Index zu machen wo man noch nicht weis ob das Device überhaupt Aktiv ist scheint mir nicht der richtige weg. Also alle Device die dort angezeigt werden sollen bei einem Klick auf dem jeweiligen Eintrag der aktuellen Komponente zugewiesen werden. Nur die Lösung mit Tstrings ist ungenügend da nicht aus wählbar. gruss |
AW: Komponente umstellen
1) In Create kannst Du das nicht lösen. Das ist nicht möglich.
Also musst Du das später tun und Deine Subcontrols vor möglichen Zugriffen auf Nil prüfen oder sie immer erzeugen und Visible := False zuweisen. 2) Ich verstehe nicht, warum Du die Strings im Formular speichern willst. Die kannst Du doch entweder fest in der Komponente fixieren oder sie jeweils dynamisch zuweisen. Dann bauchst Du nur einen String und kannst prüfen, ob der zu der aktuellen Liste auf dem aktuellen System passt. Die Liste aller denkbaren Einträge müssen dann nicht im Formular gespeichert werden. |
AW: Komponente umstellen
Zitat:
Zitat:
Das erste Device existiert immer. Die AppVolume kann, muss aber nicht eingebunden werden. (Anwendungsabhängig) Wenn ich eine Liste habe im ObjektInspektor dann kann ich anhand der Einträge Device dynamisch addieren. Oder direkt so wie in meinem Sample. Die nicht aktiven Device kann man dann anhand des aktiven Status deaktivieren. Der sinn des ganzen ist einfach. Wenn ich einen festen Font einer Komponente ändern will dann mache ich das im ObjektInspektor und schreibe dafür nicht extra Code PS: Ok! Ich gebe es auf mit dem Inspektor. 1 Gerät und die Anwendungslautstärke wird addiert. Will man ein anderes Gerät verwenden muss man dieses aus der Combo laden. Dann ändert sich das Default Gerät entsprechend. gruss |
AW: Komponente umstellen
Du kannst eine eigene Klasse von TStrings ableiten und dafür dann einen Editor registrieren (RegisterComponentEditor). Da kannst du dich dann austoben was der Benutzer wie auswählen können soll.
Zu dem Problem mit Loaded: Ich glaube ohne mehr Quelltext lässt sich da nicht viel mehr helfen, da so nicht nachvollziehbar ist wo deine Probleme auftreten. Möglich ist das jedenfalls sicher... |
AW: Komponente umstellen
Zitat:
![]() AudioVolume2 mit AppVolume im Inspektor ändern True/False Dann Form schließen/öffnen und dann wundern das es nicht läuft. Zur Laufzeit geht es weil ich den Wert Quelltextmäßig ändere (Das soll nachher deaktiviert werden wenn das umschalten funktioniert.)
Delphi-Quellcode:
AudioVolume2.AppVolume := True;
Einen letzten Versuch ist es wert. gruss |
AW: Komponente umstellen
Im SetAppVolume werden diverse Komponenten erstellt, aber keine freigegeben. Wenn ich also mehrfach umschalte, wird immer mehr Speicher verbraucht.
Was ich an dem Konzept gar nicht verstehe: Es werden doch die selben Komponenten verwendet, egal ob AppVolume True oder False ist soweit ich das sehe. Warum werden da verschiedene erstellt statt einfach immer die gleichen zu benutzen? So hast du eine pbMasterMeter und eine pbAppMeter usw., alles doppelt. Da die gleichzeitig nie verwendet werden, macht das doch keinen Sinn... Wenn du nur ein Set an Komponenten hast und dieses nur je nach Einstellung so oder so nutzt, wird es auch funktionieren... Die Anzeige kannst du dann in Loaded aktualisieren, aber die Komponenten sind dann immer da. Fehler bekommst du, wenn du erst in Loaded die Komponenten initialisierst, weil auch Left usw. bereits vorher gesetzt werden und du in WMSize usw. die Komponenten schon nutzt. Debuggen kannst du das sehr einfach indem du die IDE als Hostanwendung des Packages einträgst. |
AW: Komponente umstellen
Zitat:
Das MasterVolume ist nicht gleich AnwendungsVolume. Siehe!
Delphi-Quellcode:
Für die anderen Device sind sie gleich ....
WM_EndpointVolume:
begin PVolMuteRec := PVolMute(Msg.WPARAM); if Assigned(tbMasterVolume) then begin tbMasterVolume.Position := round((1.0 - PVolMuteRec^.Volume) * tbMasterVolume.Max); // **** Added cbMasterMute.Checked := PVolMuteRec^.Muted; // **** Added end; end; WM_VolumeEvent: begin PVolMuteRec := PVolMute(Msg.WPARAM); if Assigned(tbAppVolume) then begin tbAppVolume.Position := round((1.0 - PVolMuteRec^.Volume) * tbAppVolume.Max); // **** Added cbAppMute.Checked := PVolMuteRec^.Muted; // **** Added end; if (MyVolSet and (abs(PVolMuteRec^.Volume - MyVolVal) < 0.0001)) then MyVolSet := false else if (MyMuteSet and (PVolMuteRec^.Muted = MyMuteVal)) then MyMuteSet := false; end; Aber Device ist nicht gleich AppVolumen. Dafür benötige ich 2 Unterschiedliche Slider. Zitat:
AppVolume wird in SetAppVolume zugewiesen MasterVolume(Device) in SetComponents Hingegen tbMasterVolume ist für alle Device gleich. Zitat:
Aber Wahlweise. Zitat:
Zitat:
PS: Hab das jetzt gefixt mit der AppVolume. Das umschalten geht jetzt und die Ressourcen werden freigegeben. Mit der Liste muss ich noch überlegen ob das sinn macht und wie groß der Aufwand dafür ist. gruss |
AW: Komponente umstellen
Find nix vernünftiges über RegisterComponentEditor
Hab ich schon gelesen ![]() Benötige ich eine Kombination von TPropertyEditor und TComponentEditor um Propertys addieren zu können? gruss |
AW: Komponente umstellen
Jetzt wollte ich antworten und da ist die Frage weg... ;-)
Konkretisiere mal, wo es jetzt klemmt. Dein Propertyeditor funktioniert jetzt und jetzt brauchst Du einen Komponenteneditor? [Edit] ... Frage steht ja da... ProptertyEditor und Komponenteneditor hat miteinander nicht direkt etwas zu tun. Angenommen, Du hast eine published Property MyPath. Der kannst Du im Objektinspektor einen Text "C:\Test" zuweisen. Wenn Du dem Programmierer die Textsuche erleichtern willst kannst Du einen Propertyeditor bauen. Über die ... kann er den öffnen und darüber einen Pfad auswählen. In MyPath steht dann exakt das Gleiche drin wie vorher. Der Propertyeditor erleichtert nur die Zuweisung. Ein Komponenteneditor geht darüber hinaus und ermöglicht es, mehrere Propertys einer Komponente komplett einzurichten. Das Handling ist allerdings umfangreicher. M.E. ist das für Dich der richtige Weg. Ich weiß nicht, warum Du eine Liste in Deinen Komponenten speichern willst. Eigentlich brauchst Du doch nur einen passenden Wert!? Was ist jetzt eigentlich Deine Komponente? So eine Groupbox mit den 5 Controls oder etwas übergeordnetes, das diese Groupboxen erzeugt? |
AW: Komponente umstellen
Zitat:
jaenicke meint das geht nur über den Komponenteneditor. Das Beispiel das ich gelöscht habe funktioniert nicht. gruss |
AW: Komponente umstellen
Zitat:
Und das ist mein Problem. Wenn unter published steht
Delphi-Quellcode:
property AudioDevice: TStrings read GetAudioDevice write SetAudioDevice;
Dann steht das AudioDevice im OI als TStrings ich möchte aber eine Liste. Das soll mit der Class TComponentEditor lösbar sein nur wie ? gruss |
AW: Komponente umstellen
Da wir uns miteinander verheddert hatten, hier nochmal die letzte Frage...
Zitat:
|
AW: Komponente umstellen
Zitat:
![]() Aber vielleicht sollte ich deinen Rat beherzigen :) Zitat:
|
AW: Komponente umstellen
Für dich sollte RegisterPropertyEditor reichen, ich hatte das falsche hingeschrieben. :oops:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:39 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