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

时间:2016-08-19 14:40:16

标签: media-player inno-setup pascalscript

我写了以下代码,以便在安装程序完成程序安装后逐渐淡出视频播放卷。

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。但是当这个重复过程开始时,

  • WizardForm正常显示,但wpFinished页面中未显示任何内容。只显示一个空表单。除WizardForm.Caption之外,表格中没有任何内容。它表现得像冻结,直到重复过程(循环)结束。

  • 音量永远不会正常降低或逐渐降序。

  • 循环结束后,日志输出-10000WizardForm正常显示,页面也正常显示。音量突然停止,因为我设置为DSStopMediaPlay

如何在没有任何冻结或异常的情况下正确执行上述过程(逐渐减少视频播放声音)?

更新

当用户的系统声音在Windows中的声音控制面板中设置为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中的声音控制面板中设置为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

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

提前致谢。

1 个答案:

答案 0 :(得分:1)

因为你在循环中停止了窗口消息泵。什么会冻结窗口,也可能会阻止音量淡出。

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

要实施计时器,请使用InnoCallback DLL

[Files]
Source: InnoCallback.dll; Flags: dontcopy

[Code]

type
  TTimerProc = procedure(H: LongWord; Msg: LongWord; IdEvent: LongWord; Time: LongWord);

function SetTimer(hWnd: longword; nIDEvent, uElapse: LongWord; lpTimerFunc: LongWord): LongWord; external 'SetTimer@user32.dll stdcall';
function WrapTimerProc(Callback: TTimerProc; ParamCount: Integer): LongWord; external 'wrapcallback@files:innocallback.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);
var
  VolumeFadeCallback: LongWord;
begin
  if CurPageID = wpFinished then
  begin
     VideoHandler.Release;
     VideoHandler.Close;

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