Control pour changer le volume principal

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

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.