Control pour changer le volume principal

Soyez le premier à donner votre avis sur cette source.

Vue 15 103 fois - Téléchargée 1 062 fois

Description

Ce petit utilitaire permet simplement de changer le volume principal.

La fenetre est tres discrete (cf. capture d'ecran ^^) et n'apparait pas dans la barre des taches. Elle peut etre deplacee ou l'on veut en cliquant / deplacant avec le bouton droit de la souris. Comme le prog est toujours visible, il est en permanence accessible sans avoir a passer par le controle du volume de Windows qui met un temps fou a s'ouvrir (du moins sur mon PC :)

Le programme gere entre autres :

- la gestion du volume principal (on trouve beaucoup de code sources pour changer le volume "WAV" mais tres peu pour changer le volume "MASTER" !)
- comment dessiner une fenetre "a la main" avec les fonctions de dessin de Delphi
- Gestion simple d'un fichier .ini pour sauvegarder la position de la fenetre
- Gestion de la souris pour "glisser / deplacer" la fenetre et gerer un effet de "rollover"

Source / Exemple :


unit main;

interface

uses	Windows,	Messages, SysUtils, Classes, Graphics,	Controls, Forms, Dialogs, mmsystem,
		ExtCtrls, StdCtrls, ComCtrls,	shellApi, IniFiles;

type

	TForm1	= class(TForm)
    Timer1: TTimer;
	 procedure FormCreate(Sender:	TObject);
	 procedure FormShow(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure FormPaint(Sender: TObject);
	 
	private
	 {	Déclarations privées	}
	public
	 {	Déclarations publiques }
	end;

const FORM_BORDER = 1;
const SLIDER_HEIGHT = 8;
const SLIDER_WIDTH = 2;
const BORDER_COLOR = $0000FF;

var

	Form1: TForm1;
	masterVolumeID:DWORD;
	nid :	TNotifyIconData;
  pDragging : string;
  pLastVolumeLevel: DWORD;
  pIniFile: TIniFile;

implementation

{$R *.DFM}

{ Dessine le contour de la fenetre
  en utilisant la couleur donnee }
procedure drawBorder(iColor: longWord);
begin
  with Form1.Canvas do begin
    brush.Color := iColor;
    fillRect(rect(0, 0, form1.width, 1));
    fillRect(rect(form1.width - 1, 0, form1.width, form1.height));
    fillRect(rect(0, form1.height - 1, form1.width, form1.height));
    fillRect(rect(0, 0, 1, form1.height));
  end;
end;

{ Verifie si le curseur de la souris
  est dans la fenetre }
function mouseInside(): boolean;
begin
	result := (mouse.CursorPos.x > form1.left) and (mouse.cursorPos.x < form1.Left + form1.width) and (mouse.cursorPos.y > form1.Top) and (mouse.cursorPos.y < form1.top + form1.height);
end;

{ Dessine la fenetre, en positionnant le curseur en fonction
  du volume. }
procedure updateVolumeControl(iVolumeLevel: DWORD; iBorderColor: longWord);
var positionPercent : real;
    sliderRect: TRect;
    barHeight: integer;
begin
	{ Recupere la position du curseur
    en pourcentage (0.0 en bas et 1.0 en haut) }
  sliderRect := rect(0,0,0,0);
  if iVolumeLevel <= 0.0 then begin
  	positionPercent := 0.0;
  end else begin
	  positionPercent := iVolumeLevel / 65535.0;
  end;

	if positionPercent < 0.0 then positionPercent := 0.0;
	if positionPercent > 1.0 then positionPercent := 1.0;

  with Form1.Canvas do begin
  	{ Peint la fenetre en noir }
    Brush.Color := $000000;
    FillRect(Form1.ClientRect);
    barHeight := Form1.clientRect.bottom - Form1.clientRect.top;

    { Calcule le rectangle du curseur de volume }
    sliderRect.top := FORM_BORDER + round((1.0 - positionPercent) * (barHeight - SLIDER_HEIGHT - 2 * FORM_BORDER));
    sliderRect.left := FORM_BORDER;
    sliderRect.bottom := sliderRect.top + SLIDER_HEIGHT;
    sliderRect.right := sliderRect.left + SLIDER_WIDTH;

    { Peint le curseur }
    brush.color := $FFFFFF;
    fillRect(sliderRect);
  end;

	{ Dessine le contours de la fenetre }
  drawBorder(iBorderColor);
end;

{ Recupere l'identifiant du mixeur donne
  L'identifiant servira par exemple a recuperer
  le volume }
function	GetMixerControlID(CompType: integer) : DWORD;
var	mxl: MIXERLINE;
	mxc: MIXERCONTROL ;
	mxlc: MIXERLINECONTROLS ;
begin

	mxl.cbStruct	:=	sizeof(mxl);
	mxl.dwComponentType := CompType;

	Result	:=	0;
	
	if (mixerGetLineInfo(0, @mxl, MIXER_GETLINEINFOF_COMPONENTTYPE)	=
MMSYSERR_NOERROR)	then begin
	 mxlc.cbStruct	:=	sizeof(mxlc);
	 mxlc.dwLineID	:=	mxl.dwLineID;
	 mxlc.dwControlType := MIXERCONTROL_CONTROLTYPE_VOLUME;
	 mxlc.cControls := mxl.cControls;
	 mxlc.cbmxctrl	:=	sizeof(mxc);
	 mxlc.pamxctrl	:=	@mxc;
	 if (mixerGetLineControls(0, @mxlc,	MIXER_GETLINECONTROLSF_ONEBYTYPE) =
MMSYSERR_NOERROR)	then Result	:=	mxc.dwControlID;
	end;

end;

{ Retourne le volume du composant donne }
function	GetVolume( nIDControl: DWORD)	: DWORD;
var	Volume :	Array[0..1]	Of	TMixerControlDetails_Unsigned;
		mxcd: TMixerControlDetails;

begin

	mxcd.cbStruct := sizeof(mxcd);
	mxcd.dwControlID := nIDControl;
	mxcd.cChannels := 2;
	mxcd.cMultipleItems := 0;
	mxcd.cbDetails := sizeof(MIXERCONTROLDETAILS_UNSIGNED)	* 2;
	mxcd.paDetails := @Volume;
	Result	:=	0;

  try
  	mixerGetControlDetails(0, @mxcd,	MIXER_GETCONTROLDETAILSF_VALUE);
    Result	:=	Volume[0].dwValue;
  except

  end;
end;

{ Change le volume du composant donne }
function	SetVolume(ID, Value:	DWord): Boolean;
var	Volume	: Array[0..1] Of TMixerControlDetails_Unsigned;
		 mxcd: TMixerControlDetails;
begin	
	Volume[0].dwValue	:=	Value; 
	Volume[1].dwValue	:=	Value; 
	With mxcd Do 
		Begin	
			cbStruct	:=	SizeOf(mxcd); 
			dwControlID	:=	ID; 
			cChannels := 2; 
			cMultipleItems	:=	0;	
			cbDetails := SizeOf(TMixerControlDetails_Unsigned)	* 2; 
			paDetails := @Volume;
			Result := (mixerSetControlDetails(0, @mxcd,
MIXER_SETCONTROLDETAILSF_VALUE) = MMSYSERR_NOERROR); 
		End; {With}	
End;

procedure TForm1.FormCreate(Sender:	TObject);
begin
	{  pDragging indique le type de deplacement en cours:
   - soit le deplacement du curseur de volume (pConfig = 'slider')
   - soit le deplacement de la fenetre (pConfig = 'form')
   - soit rien (pConfig = 'none' }
  pDragging := 'none';

  { Recupere l'identifiant du control de volume principal }
  masterVolumeID := GetMixerControlID(MIXERLINE_COMPONENTTYPE_DST_SPEAKERS);
  pLastVolumeLevel := 99999;

  { Change la taille de la fenetre }
  Form1.width := FORM_BORDER * 2 + SLIDER_WIDTH;

  Timer1.enabled := false;

  { Lit la position de la fenetre dans le fichier .ini }
	pIniFile := TIniFile.Create(ExtractFilePath(Application.ExeName) + 'changerVolume.ini');
  form1.left := strToInt(pIniFile.readString('CONFIG', 'form.left', '50'));
  form1.top := strToInt(pIniFile.readString('CONFIG', 'form.top', '50'));

  pIniFile.Free;
end;

procedure TForm1.FormShow(Sender: TObject);
begin
	{ Enleve l'application de la barre des taches }
	ShowWindow(Application.Handle, SW_HIDE);
end;

{ Le timer est actif uniquement lorsque
  l'on clique sur la fenetre }
procedure TForm1.Timer1Timer(Sender: TObject);
begin
	{ Code pour deplacer la fenetre }
  if pDragging = 'form' then begin
  	form1.left := Mouse.CursorPos.x;
    form1.top := Mouse.CursorPos.y;
    if form1.Left + form1.width > screen.Width then form1.left := screen.width - form1.width;
    if form1.Left < 0 then form1.left := 0;
    if form1.top + form1.height > screen.height then form1.top := screen.height - form1.height;
    if form1.top < 0 then form1.top := 0;
  end else begin
    { Si la souris n'est plus
     a l'interieur de la fenetre
     on desactive le timer }
  	if not mouseInside() then begin
    	if pDragging = 'none' then begin
	    	Timer1.enabled := false;
	      drawBorder($000000);
      end;
    end;
  end;
end;

{ MouseDown }
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
	{ Click gauche: on change le volume
    Click droit: on commence a deplacer la fenetre }
	if button = mbLeft then begin
	  pDragging := 'slider'
  end else begin
  	pDragging := 'form';
    Timer1.enabled := true;
  end;
end;

{ MouseUp }
procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  { Sauvegarde la position de la fenetre dans le fichier .ini }
	if pDragging = 'form' then begin
		pIniFile := TIniFile.Create(ExtractFilePath(Application.ExeName) + 'changerVolume.ini');
	  pIniFile.writeString('CONFIG', 'form.left', intToStr(form1.left));
	  pIniFile.writeString('CONFIG', 'form.top', intToStr(form1.top));
	  pIniFile.Free;
  end;
  pDragging := 'none';
end;

{ MouseMove }
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var volumeLevel:integer;
begin
	{ Changement du volume }
  if pDragging = 'slider' then begin
  	{/ Calcule le nouveau volume }
    volumeLevel := 65535 - round(y / Form1.Height * 65535);
    if volumeLevel > 65535 then volumeLevel := 65535;
    if volumeLevel < 0 then volumeLevel := 0; 

    { On redessine la fenetre et on change le volume }
    updateVolumeControl(volumeLevel, BORDER_COLOR);
    SetVolume(masterVolumeID, volumeLevel);
  end else begin
  	{ Sinon on redessine juste la fenetre
      pour l'effet de "rollover" }
  	volumeLevel := getVolume(masterVolumeID);
    updateVolumeControl(volumeLevel, BORDER_COLOR);
  end;

  Timer1.enabled := enabled;
end;

{ OnPaint }
procedure TForm1.FormPaint(Sender: TObject);
var volumeLevel:integer;
begin
	{ On redessine juste la fenetre
    en utilisant le volume courant }
	volumeLevel := getVolume(masterVolumeID);
  updateVolumeControl(volumeLevel, $000000);
end;

end.

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

Messages postés
24
Date d'inscription
jeudi 19 juin 2003
Statut
Membre
Dernière intervention
15 décembre 2008

Salut, Vista gère le volume d'une façon complètement différente donc il y a en effet peu de chance que ce programme fonctionne correctement.

Il me semble que Vista gère le volume par programme plutôt que globalement, mais je n'ai aucune idée de la façon de controler ça avec Delphi.
Messages postés
1
Date d'inscription
samedi 18 août 2007
Statut
Membre
Dernière intervention
20 août 2007

Superbe utilitaire !!!
Merci d'avoir diffusé la source.
Cela fonctionne très bien sur Windows XP mais n'est malheureusement pas
pris en compte sur Win VISTA :(
Si vous avez une solution... N'hésitez pas a me contacter.
En attendant, Je cherche de mon coté
Kiss :D
Messages postés
3
Date d'inscription
lundi 6 février 2006
Statut
Membre
Dernière intervention
11 août 2006

merci laurent pour ton code il m'a été super utile, j'ai mis un peu de temps un comprendre et à isoler le minimum nécessaire pour gérer uniquement le MASTER VOLUME (et oui çà fait pas plus d'une semaine que je connais delphi :)) mon code est peut être pas super bon ya des truc pas très ergonomique dû à l'appli que je veux faire derrière, en tout cas si çà peut aider des novices comme moi, je laisse ici le code que j'ai modifié, encore une fois merci beaucoup Laurent ;)


unit volume;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,
mmsystem, ExtCtrls, StdCtrls, ComCtrls, shellApi, IniFiles;

type
TForm1 = class(TForm)
Edit1: TEdit;
Memo1: TMemo;
volumeBar: TProgressBar;
procedure teditkeypressed(Sender: TObject; var Key: Char);
procedure FormCreate(Sender: TObject);
procedure change_volume(volume: string);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
masterVolumeID:DWORD;
implementation

{$R *.dfm}

// gets the ID of the wanted mixer
function GetMixerControlID(CompType: integer) : DWORD;
var mxl: MIXERLINE;
mxc: MIXERCONTROL ;
mxlc: MIXERLINECONTROLS ;
begin

mxl.cbStruct := sizeof(mxl);
mxl.dwComponentType := CompType;

Result := 0;

if (mixerGetLineInfo(0, @mxl, MIXER_GETLINEINFOF_COMPONENTTYPE) =
MMSYSERR_NOERROR) then begin
mxlc.cbStruct := sizeof(mxlc);
mxlc.dwLineID := mxl.dwLineID;
mxlc.dwControlType := MIXERCONTROL_CONTROLTYPE_VOLUME;
mxlc.cControls := mxl.cControls;
mxlc.cbmxctrl := sizeof(mxc);
mxlc.pamxctrl := @mxc;
if (mixerGetLineControls(0, @mxlc, MIXER_GETLINECONTROLSF_ONEBYTYPE) =
MMSYSERR_NOERROR) then Result := mxc.dwControlID;
end;

end;

// gives the volume of the given componant
function GetVolume( nIDControl: DWORD) : DWORD;
var Volume : Array[0..1] Of TMixerControlDetails_Unsigned;
mxcd: TMixerControlDetails;

begin

mxcd.cbStruct := sizeof(mxcd);
mxcd.dwControlID := nIDControl;
mxcd.cChannels := 2;
mxcd.cMultipleItems := 0;
mxcd.cbDetails := sizeof(MIXERCONTROLDETAILS_UNSIGNED) * 2;
mxcd.paDetails := @Volume;
Result := 0;

try
mixerGetControlDetails(0, @mxcd, MIXER_GETCONTROLDETAILSF_VALUE);
Result := Volume[0].dwValue;
except

end;
end;


// Changes the volume of the given componant
function SetVolume(ID, Value: DWord): Boolean;
var Volume : Array[0..1] Of TMixerControlDetails_Unsigned;
mxcd: TMixerControlDetails;
begin
Volume[0].dwValue := Value;
Volume[1].dwValue := Value;
With mxcd Do
Begin
cbStruct := SizeOf(mxcd);
dwControlID := ID;
cChannels := 2;
cMultipleItems := 0;
cbDetails := SizeOf(TMixerControlDetails_Unsigned) * 2;
paDetails := @Volume;
Result := (mixerSetControlDetails(0, @mxcd,
MIXER_SETCONTROLDETAILSF_VALUE) = MMSYSERR_NOERROR);
End; {With}
End;



procedure TForm1.change_volume(volume: string);
var
volume_int:integer;
current_volume: DWord;
begin
current_volume:= round(GetVolume( GetMixerControlID(MIXERLINE_COMPONENTTYPE_DST_SPEAKERS))/655); // before calculating we get the current volume so that we can keep it if we want to
edit1.Text:=''; // only for the demonstration reset the text in edit1
if trystrtoint(volume,volume_int) then // checks if the volume entered is an integer
else volume_int:=999999; // if not, puts 999999 as the value of the integer meant to represent the volume
if volume_int=999999 then // if volume was not an integer then
if volume='min' then
volume_int:=0
else if volume='max' then
volume_int:=100
else if volume='+' then
volume_int:=round(current_volume*1.1)
else if volume='-' then
volume_int:=round(current_volume*0.9)
else volume_int:=current_volume; // if volume is nothing expected, it remains as it was
SetVolume(GetMixerControlID(MIXERLINE_COMPONENTTYPE_DST_SPEAKERS), volume_int*655); // set the volume of the component MASTER VOLUME to volume_int wich is between 0 and 100 multiplied by 655 because the component wants a value between 0 and 65535
volumebar.Position:=volume_int; //only for the demonstration fills the bar of the left with a value representing the volume
end;



procedure TForm1.FormCreate(Sender: TObject);
begin
edit1.Text:=''; // removes the text 'edit1' from the Edit1 object
Memo1.text:=' SET MASTER VOLUME'+#13#10#13#10+'0-100 --> percentage of volume'+#13#10+'min --> set volume to the minimum'+#13#10+'max --> set volume to the maximum'+#13#10+'+ --> increase the volume by 10%'+#13#10+'- --> decrease the volume by 10%';
change_volume(trim(edit1.text)); // to run the procedure while launching the program so that the volume bar will show us the volume immediately
end;

procedure TForm1.teditkeypressed(Sender: TObject; var Key: Char);
begin

if key=#13 then change_volume(trim(edit1.text)); // change the volume when the user presses ENTER
end;

end.

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.