在 Inno Setup 中逐渐淡化 TDirectShow Player(Inno Media Player)音量

Fade TDirectShow Player (Inno Media Player) volume gradually in Inno Setup

我编写了以下代码以在安装程序完成安装我的程序时逐渐降低视频播放音量。

procedure CurPageChanged(CurPageID: Integer);
var
   X: Integer;
begin
  ... 
  if CurPageID = wpFinished then
  begin
    VideoHandler.Release;
    VideoHandler.Close;
    DSSetVolume(-0);
    X := 0;
    repeat
      DSSetVolume(X);
      Log(IntToStr(X));
      X = X - 1;
    until X = -10000;
    DSStopMediaPlay;
  ...
  end;
  ...
end;

上面的代码输出了 X 值,因为我希望逐渐减小音量,我可以在日志中看到它像 -1 , -2 ... -10000 一样。但是当这个重复过程开始时,

如何才能正确地完成上述过程(逐渐降低视频播放声音)而不出现任何卡顿或异常情况?

更新

当在 Windows.[=22= 的声音控制面板中将用户的系统声音设置为 20% 时,以下代码可以提供最佳效果]

procedure VolumeFadeTimerProc(HandleW, msg, idEvent, TimeSys: LongWord);
begin
  MPEGVideoVolume := MPEGVideoVolume - 15;
  if MPEGVideoVolume < -4000 then
  begin
    DSStopMediaPlay;
    KillTimer( 0, TimerID);
    KillTimer( 0, VolumeFadeTimer);
    Log('Volume Fade Timer has been reset.');
  end
    else
  begin
    Log('MPEG Video Volume has been set to: ' + IntToStr(MPEGVideoVolume));
    DSSetVolume(MPEGVideoVolume);
  end;
end;

减量为15

最大减量为-4000

当在 Windows.[=22= 的声音控制面板中将用户的系统声音设置为 100% 时,以下代码可以提供最佳效果]

procedure VolumeFadeTimerProc(HandleW, msg, idEvent, TimeSys: LongWord);
begin
  MPEGVideoVolume := MPEGVideoVolume - 35;
  if MPEGVideoVolume < -10000 then
  begin
    DSStopMediaPlay;
    KillTimer( 0, TimerID);
    KillTimer( 0, VolumeFadeTimer);
    Log('Volume Fade Timer has been reset.');
  end
    else
  begin
    Log('MPEG Video Volume has been set to: ' + IntToStr(MPEGVideoVolume));
    DSSetVolume(MPEGVideoVolume);
  end;
end;

减量为35

最大减量为-10000

是否需要根据用户设置的系统声音量自动更改音量减小量和最大减小量?

提前致谢。

因为您停止了循环中的 window 消息泵。是什么冻结了 window 并且可能还阻止了音量淡出。

您必须使用计时器来淡出音量而不冻结消息泵。

[Code]

function SetTimer(
  hWnd: longword; nIDEvent, uElapse: LongWord; lpTimerFunc: LongWord): LongWord;
  external 'SetTimer@user32.dll stdcall';

var
  Volume: Integer;
  VolumeFadeTimer: LongWord;

procedure VolumeFadeTimerProc(
  H: LongWord; Msg: LongWord; IdEvent: LongWord; Time: LongWord);
begin
  { Fade by -1000 every 100 ms }
  Volume := Volume - 1000;
  if Volume <= -10000 then
  begin
    DSStopMediaPlay;
    KillTimer(0, VolumeFadeTimer);
  end
    else
  begin
    DSSetVolume(Volume);
  end;
end;

procedure CurPageChanged(CurPageID: Integer);
begin
  if CurPageID = wpFinished then
  begin
     VideoHandler.Release;
     VideoHandler.Close;

     Volume := 0;
     { call VolumeFadeCallback every 100 ms }
     VolumeFadeTimer := SetTimer(0, 0, 100, CreateCallback(@VolumeFadeTimerProc));
     DSSetVolume(Volume);
  end;
end;

对于 CreateCallback function, you need Inno Setup 6. If you are stuck with Inno Setup 5, you can use WrapCallback function from InnoTools InnoCallback 库。