![]() |
AW: TAudioVolume Komponente incl. System Mixer
Wenn man Windows-Funktionen nachbaut, dann kommt man nicht drum herum für die verschiedenen Windows-Versionen entsprechende Pfade zu bauen.
Delphi-Quellcode:
Aber ich weiß schon was du als nächstes schreiben wirst:
if WindowsVersionAnnoDazumal then
... else if WindowsVersionEtwasNeuer then ... else ... end. Zitat:
|
AW: TAudioVolume Komponente incl. System Mixer
Zitat:
Grüße Dalai |
AW: TAudioVolume Komponente incl. System Mixer
Zitat:
![]() Kannst du ein Icon sehen? Wenn ja dann ist das Problem schon 12 Beiträge vorher erledigt gewesen. :)
Delphi-Quellcode:
function TAudioVolume.SetSysItemIcon(wsItems: PWideChar): TIcon;
var fi: TSHFileInfoW; begin Result := nil; ZeroMemory(@fi, SizeOf(TSHFileInfo)); if SHGetFileInfoW(PWideChar(wsItems), 0, fi, SizeOf(TSHFileInfo), SHGFI_DISPLAYNAME Or SHGFI_SYSICONINDEX or SHGFI_LARGEICON or SHGFI_ICON) <> 0 then begin Icon := TIcon.Create; Icon.Handle := fi.HICON; Result := Icon; end; end;
Delphi-Quellcode:
var
WinDir: array [0..MAX_PATH] of WideChar; //... FillChar(WinDir, sizeof(WinDir), 0); GetWindowsDirectory(WinDir, MAX_PATH); MasterImg.Picture.Icon := SetSysItemIcon(PWideChar(WinDir + '\System32\SndVol.exe')); Oh.. danke Zitat:
Tigü mein Hasi.. Nehme mir bitte nicht so viel Arbeit ab, habe dann ja nichts mehr zu tun ;) Zitat:
Es zwingt mich niemand das Icon über die Ordinal Nummer zu laden das geht auch anders. gruss |
AW: TAudioVolume Komponente incl. System Mixer
Neue Version nur Master Icon addiert.
Mache jetzt erst mal pause mit dem Kram wegen den Event Problemen. Hier ein Beispiel!
Delphi-Quellcode:
Ich erstelle das Event.
unit AudioSessionNotification;
interface uses Windows, Messages, Classes, AudioSessionControl, Constants; type IAudioSessionNotification = interface(IUnknown) ['{641DD20B-4D41-49CC-ABA3-174B9477BB08}'] function OnSessionCreated(const NewSession: IAudioSessionControl): HResult; stdcall; end; TAudioSessionNotification = class(TInterfacedObject, IAudioSessionNotification) private MsgHandle: HWND; public function OnSessionCreated(const NewSession: IAudioSessionControl): HResult; stdcall; procedure SetMsgHandle(WinHandle: HWND); end; implementation { TSessionNotification } function TAudioSessionNotification.OnSessionCreated(const NewSession: IAudioSessionControl): HResult; begin PostMessage(MsgHandle, WM_SessionCreate, integer(@NewSession), 0); Result := S_OK; end; procedure TAudioSessionNotification.SetMsgHandle(WinHandle: HWND); begin MsgHandle := WinHandle; end; end.
Delphi-Quellcode:
Dann registriere ich das Notification
TAudioVolume.Create..
var ISessionNotification: TAudioSessionNotification; //... // SessionNotification ISessionNotification := TAudioSessionNotification.Create; ISessionNotification.SetMsgHandle(FEventHandle); SessionNotification := ISessionNotification;
Delphi-Quellcode:
Jetzt sollte hier wenn eine neue Session erstellt wird außerhalb der Anwendung
// Register TAudioSessionNotification to receive a notification when a session is created.
HR := SessionManager2.RegisterSessionNotification(SessionNotification); if HR <> S_OK then raise Exception.Create('Error : Unable to Register Session Notification');
Delphi-Quellcode:
Das Event feuern tut es aber nicht auch das nicht OnSessionDisconnected.
function TAudioSessionNotification.OnSessionCreated(const NewSession: IAudioSessionControl): HResult;
begin PostMessage(MsgHandle, WM_SessionCreate, integer(@NewSession), 0); Result := S_OK; end; Das war nur zur Info. Ihr habt den Source also tobt euch aus. gruss |
AW: TAudioVolume Komponente incl. System Mixer
Diese Zeilen bedürfen einen Überarbeitung:
Delphi-Quellcode:
Bei jedem Resize (und das sind bis zum ersten Zeigen des Formulars schon sechs) wird ein Icon erstellt. Das vorige wird aber nie freigegeben -> Speicherleck.
procedure TAudioVolume.WMSize(var Message: TWMSize);
var WinDir: array [0..MAX_PATH] of WideChar; begin ... FillChar(WinDir, sizeof(WinDir), 0); GetWindowsDirectory(WinDir, MAX_PATH); MasterImg.Picture.Icon := SetSysItemIcon(PWideChar(WinDir + '\System32\SndVol.exe')); Das Ermitteln des Windows Directory und das Setzen des Icons brauchst du ja nicht bei jedem Resize machen. Schiebe das und die Erzeugung von MasterImg in
Delphi-Quellcode:
.
procedure TAudioVolume.SetMasterComponents;
|
AW: TAudioVolume Komponente incl. System Mixer
Hm...die anderen Icons von den Anwendungen leaken auch...versuch mal, ob du das schöner hinkriegst.
|
AW: TAudioVolume Komponente incl. System Mixer
Delphi-Quellcode:
Wie sag ich das jetzt? Es ist etwas suboptimal! :shock:
function TAudioSessionNotification.OnSessionCreated(const NewSession: IAudioSessionControl): HResult;
begin PostMessage(MsgHandle, WM_SessionCreate, integer(@NewSession), 0); Result := S_OK; end; Du möchtest ein Interface per PostMessage weiterversenden. Erster Fehler ist das Casten des Pointers auf Integer. Außerdem wird dadurch der Referenzzählung durcheinander gebracht. Sobald OnSessionCreated durchlaufen wird, ist die Instanz nicht mehr sicher da. Das müsste eigentlich für angemeldete FOnSessionCreated-Eventhandler knallen. Zumindest tut es das bei mir, wenn man einen Eventhandler anmeldet und auf die NewSession-Instanz zugreifen will:
Delphi-Quellcode:
Dann knallt es in System.pas
procedure TForm1.AudioVolume1SessionCreated(NewSession: IAudioSessionControl);
var pRetVal: uint; begin NewSession.GetState(pRetVal); end;
Delphi-Quellcode:
Die Überlegung mit den PostMessage, um asynchron zu arbeiten und reagieren zu können ist problemlos für ordinale Typen (Byte, Integer, Cardinal...) umsetzbar, aber mit Interface-Instanzen kommst du in Teufelsküche.
procedure _IntfAddRef(const Dest: IInterface);
begin if Dest <> nil then Dest._AddRef; end; Hast du mal überlegt die IAudioSessionEvents, IMMNotificationClient, IAudioSessionNotification und IAudioEndpointVolumeCallback in TAudioVolume zu integrieren? Das wäre einfacher als so Zwischenklassen, die nichts weiter tun, als die Informationen per PostMessage weiterzuversenden. Weniger Quelltext würde sich dadurch auch ergeben. Wenn man aus einen anderen Thread-Context als den Mainthread befeuert wird, muss man natürlich synchronisieren. |
AW: TAudioVolume Komponente incl. System Mixer
Delphi-Quellcode:
function TAudioSessionNotification.OnSessionCreated(const NewSession: IAudioSessionControl): HResult;
Habe hier noch gar keine Fehler bezüglich des Pointers feststellen(debuggen) können weil das Event nie ausgelöst wird. Zitat:
Wie ich schon sagte trotz Registrierung, Initialisierung funktioniert es nicht. Zitat:
Delphi-Quellcode:
sollte reichen.
if not Assigned(MasterImg) then
begin MasterImg := TImage.Create(FMGroupBox); MasterImg.AutoSize := true; MasterImg.Parent := FMGroupBox; FillChar(WinDir, sizeof(WinDir), 0); GetWindowsDirectory(WinDir, MAX_PATH); MasterImg.Picture.Icon := SetSysItemIcon(PWideChar(WinDir + '\System32\SndVol.exe')); if Assigned(MasterImg.Picture.Icon) then begin MasterImg.Left := (ClientWidth - Icon.Width) div 2; MasterImg.Top := 5; MasterImg.Show; end else FreeAndNil(MasterImg); end; Zitat:
Delphi-Quellcode:
if Assigned(MasterImg) then
FreeAndNil(MasterImg); Zitat:
Delphi-Quellcode:
procedure TForm1.AudioVolume1SessionCreated(NewSession: IAudioSessionControl);
Sorry das muss knallen. 1. SessionCreated wird nie aufgerufen daran kann es also nicht liegen. 2. Du erstellst ein Event für eine Session was eigentlich nichts mit den\der Session zu tun hat. AudioVolume1 ist das HauptVolumen (Lautsprecher) und hat nix mit den Session zu tun. Aber du weist ihm ein SessionCreated zu :shock: Deine Zuweisung ist korrekt ein Denkfehler meinerseits. gruss |
AW: TAudioVolume Komponente incl. System Mixer
Habe den Quelltext jetzt nicht vor mir, aber ich habe in dem Beispielformular den oben genannten Eventhändler definiert und jeder tempSessionDingsbums an OnSessionCreated rangetackert. Bei neuen Programm mit Audioausgabe, z.B. FooBar2000, wurde das Event mehrfach ausgelöst. Also der Teil wo das Postmessage machst.
|
AW: TAudioVolume Komponente incl. System Mixer
Zitat:
Muss dann wohl über AudioVolume1 doch das Event initialisieren. Bin da wohl selbst über den Session und MasterVolumen Kram gestolpert. :wall::duck: Trotzdem bekomme ich kein Event.. Kann es sein das dieses nur von Anwendungen ausgelöst wird die das Interface auch unterstützen? Denn wenn ich einen meiner Player starte passiert da gar nichts. Der Mixer selbst erkennt ihn aber und addiert ihn als Session.
Delphi-Quellcode:
Hier passiert nix.
{ TSessionNotification }
function TAudioSessionNotification.OnSessionCreated(const NewSession: IAudioSessionControl): HResult; begin PostMessage(MsgHandle, WM_SessionCreate, integer(@NewSession), 0); Result := S_OK; end; Danke.. Zitat:
Bin mit dem VCL Kram nicht gerade sehr bewandert. Zitat:
gruss |
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:31 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 by Thomas Breitkreuz