Hace unos meses publicaba una unit, WinMasterVolumen, para controlar el volumen del PC con WinXP, Vista, Win7 y Win8. En esta ocasión y basada en el mismo código presento la segunda versión que añade la característica de disparar un evento cuando el volumen o el mute del sistema varían, bien por acción del usuario o por código.
El sistema callback es diferente, de nuevo, en WinXP y común en adelante. En XP se basa en un mensaje MM_MIXM_CONTROL_CHANGE. En principio es fácil de usar pero requiere un bucle de mensajes para que funcione y una ventana.
En Vista, Win7 y Win8 tenemos que echar mano de interfaces de windows y el evento es una llamada a una función (OnNotify) que usaremos para realizar el proceso.
Para conseguir que el código funcione en todos los sistemas operativos he escrito esta nueva unit que presenta una clase TMasterVolume que hará el trabajo. Esta clase tiene los siguientes funciones y precedimientos públicos:
constructor Create; destructor Destroy; override; procedure SetNotifyEvent(OnNotify: TOnNotify); procedure SetChangeStatusEvent(OnChangeStatus: TOnChangeStatus); procedure SetChangeStatusCallBack(OnChangeStatus: TOnChangeStatusCallBack); function GetMasterMute: boolean; procedure SetMasterMute(Value: boolean); function GetMasterVolume: DWORD; procedure SetMasterVolume(Value: DWORD);
Los eventos pueden ser de estos tipos:
type TOnNotify = function(pNotify: PAUDIO_VOLUME_NOTIFICATION_DATA): HRESULT; stdcall; POnNotify = ^TOnNotify; TOnChangeStatus = procedure(Volume: DWORD; Mute: boolean) of object; TOnChangeStatusCallBack = procedure(Volume: DWORD; Mute: boolean); stdcall;
SetNotifyEvent Sólo válido para vista en adelante, asigna un evento similar al usado por windows, TOnNotify . Al usar valores en coma flotante he añadido otros dos que usan DWORD siendo mas compatible en todos los S.O.
SetChangeStatusEvent Asigna un evento tipo TOnChangeStatus compatible con la VCL, es decir, será una función de nuestro Form, por ejemplo.
SetChangeStatusCallBack Asigna un evento tipo TOnChangeStatusCallBack, no compatible con VCL y diseñado para uso en programas API puros.
El resto de las funciones son equivalentes a WinMasterVolumen.
El siguiente es un ejemplo se uso usando la VCL, un formulario con un TrackBar y un CheckBox:
procedure TForm1.OnChangeStatus(MasterVolume: DWORD; Muted: boolean); begin CheckBox1.Checked:= Muted; TrackBar1.Position:= MasterVolume; end; procedure TForm1.FormCreate(Sender: TObject); begin Master:= TMasterVolume.Create; Master.SetChangeStatusEvent(OnChangeStatus); CheckBox1.Checked:= Master.GetMasterMute; TrackBar1.Position:= Master.GetMasterVolume; end; procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction); begin Master.Free; end; procedure TForm1.TrackBar1Change(Sender: TObject); begin Master.SetMasterVolume(TrackBar1.Position); end; procedure TForm1.CheckBox1Click(Sender: TObject); begin Master.SetMasterMute(CheckBox1.Checked); end;
Un ejemplo de uso con API pura en WindowsXP:
uses Windows, Messages, WinMasterVolumeClass; var Msg: TMsg; Master: TMasterVolume; procedure OnChangeStatus(Volume: DWORD; Mute: boolean); stdcall; begin // Mantenes el volumen al máximo y con mute desactivado Master.SetMasterVolume($FFFF); Master.SetMasterMute(false); end; begin Master:= TMasterVolume.Create; Master.SetMasterVolume($FFFF); Master.SetMasterMute(false); Master.SetChangeStatusCallBack(@OnChangeStatus); // bucle de mensajes repeat GetMessage(Msg, 0, 0, 0); DispatchMessage(Msg); until (Msg.Message = WM_QUIT); end.
El mismo código en Vista, Win7 y Win8. No precisa bucle de mensajes:
uses Windows, Messages, WinMasterVolumeClass; var Msg: TMsg; Master: TMasterVolume; procedure OnChangeStatus(Volume: DWORD; Mute: boolean); stdcall; begin Master.SetMasterVolume($FFFF); Master.SetMasterMute(false); end; begin Master:= TMasterVolume.Create; Master.SetMasterVolume($FFFF); Master.SetMasterMute(false); Master.SetChangeStatusCallBack(@OnChangeStatus); repeat sleep(200); until false; end.
Aunque podríamos dar más funcionalidad a esta unit, de momento la dejo como está. Espero que os sea útil.
Saludos.