2016-09-28 18 views
2

Я в процессе добавления BASS Audio Project в свой скрипт Pascal. Добавление воспроизведения музыки для очень длительной установки не плохо для пользователя. Но хорошо останавливать музыку, когда пользователь сводит к минимуму WizardForm на панели задач. И автоматически начинайте музыку, если пользователь снова восстанавливает ее с панели задач.Inno Setup Detect (получать уведомление), когда WizardForm минимизирует и восстанавливает

Мне нравится знать, как определить, удалось ли восстановить или восстановить WizardForm и приостановить или запустить воспроизведение музыки BASS в соответствии с состоянием окна WizardForm. (Использование таких функций, как BASS_Pause, BASS_Stop или BASS_Start.)

Как и что я должен сделать для этого? TWindowState или WMSYSCOMMAND?

Заранее спасибо.

ответ

2

Я не думаю, что есть какие-либо события, которые уведомит вас, когда форма мастера будет сведена к минимуму или восстановлена. TForm.WindowState также недоступен в скрипте Inno Setup Pascal.


Но вы можете запланировать частый таймер (с помощью InnoCallback DLL) и проверьте, изменения в состоянии вида.

Обратите внимание, что форма на самом деле скрыта, а не минимизирована, когда вы нажимаете кнопку «Свернуть» (анимация с минимальным уменьшением). Поэтому используйте GetWindowLong WinAPI function, чтобы проверить стиль окна WS_VISIBLE.

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

[Code] 

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

const 
    GWL_STYLE = -16; 
    WS_VISIBLE = $10000000; 

function GetWindowLong(hWnd: THandle; nIndex: Integer): LongInt; 
    external '[email protected] stdcall'; 
function SetTimer(
    hWnd: longword; nIDEvent, uElapse: LongWord; lpTimerFunc: LongWord): LongWord; 
    external '[email protected] stdcall'; 

function WrapTimerProc(Callback: TTimerProc; ParamCount: Integer): LongWord; 
    external '[email protected]:innocallback.dll stdcall'; 

var 
    WasHidden: Boolean; 

procedure HiddenTimerProc(H: LongWord; Msg: LongWord; IdEvent: LongWord; Time: LongWord); 
var 
    Hidden: Boolean; 
    Style: LongInt; 
begin 
    Style := GetWindowLong(WizardForm.Handle, GWL_STYLE); 
    Hidden := (Style and WS_VISIBLE) = 0; 
    if Hidden and not WasHidden then 
    begin 
    Log('Minimized, stopping music...'); 
    end 
    else 
    if not Hidden and WasHidden then 
    begin 
    Log('Restored, resuming music...'); 
    end; 
    WasHidden := Hidden; 
end; 

procedure InitializeWizard(); 
var 
    HiddenTimerCallback: LongWord; 
begin 
    HiddenTimerCallback := WrapTimerProc(@HiddenTimerProc, 4); 
    WasHidden := False; 
    SetTimer(0, 0, 500, HiddenTimerCallback); 
end; 
+0

Дерьмо! Я также проверил ваш ответ. Он также работает. Прежде чем я получу этот ответ, мне удалось с кодом, который не использует таймер, но с использованием 'InnoCallBack.dll'. Если я отправлю это как обновление моего вопроса, можете ли вы проверить его на предмет неправильных вещей? – GTAVLover

+0

Если это работает для вас, отправьте его как ответ. Я взгляну. –

+0

Хорошо, я скоро это сделаю. – GTAVLover

2

К сожалению, нет какого-либо Уведомлять событие, которое может сообщить вам, если WizardForm минимизируется или возрожденным потому что такое событие не является необходимым для создания инсталляций.

Если вы действительно хотите проверить, если WizardForm восстанавливается или свернутое (не проверить его видимость),


Прежде всего, необходимо изменить настройки Inno исходного кода, чтобы дать Минимизация и восстановление переходов (Анимация) для окна мастера.

Примечание: следующие изменения исходного кода успешно протестированы с помощью Inno Setup 5.5.9 Unicode и Ansi Versions.

  1. Скрытие Hidden Анкету Дельфы из программы установки Inno Setup совершенно:

    Параметры Setup.exe> ​​Project для Setup.exe> ​​Application> Target Extension File> E32.

    Щелкните правой кнопкой мыши Setup.e32> Просмотреть исходный код.

    Изменение { Initialize ... Секции программы установки следующим образом:

    Добавитьif shWindowVisible in SetupHeader.Options thenперед линиейShowWindow(Application.Handle, SW_SHOW);.

    Изменение { Run } Раздел программы установки, как это:

    ... 
    { Run } 
    try 
        Application.MainFormOnTaskBar := False; 
        Application.ShowMainForm := False; 
        ShowWindow(Application.Handle, SW_HIDE); 
        Application.Run; 
    except 
    ... 
    

    Вы сделали! Теперь он будет скрыт.

    Для получения дополнительной информации см. Setup Programs created using Inno Setup Compiler doesn't display Minimize Animation.

  2. Добавление Минимизация и восстановление переходов (Animations) для Inno мастера установки формы:

    В мастере единицы,

    ИзменитьTWizardForm.CreateParamsтак:

    procedure TWizardForm.CreateParams(var Params: TCreateParams); 
    begin 
        inherited; 
        { Ensure the form is on top of MainForm by making MainForm 
        the "parent" of the form when *MainForm is set to Visible*. } 
        if shWindowVisible in SetupHeader.Options then 
        Params.WndParent := MainForm.Handle 
        else 
        Params.WndParent := GetDesktopWindow; 
    end; 
    

    ИзменениеTWizardForm.WMSysCommandтак:

    procedure TWizardForm.WMSysCommand(var Message: TWMSysCommand); 
    begin 
        if Message.CmdType and $FFF0 = SC_MINIMIZE then begin 
        { A minimize button is shown on the wizard form when (shWindowVisible in 
         SetupHeader.Options). When it is clicked we want to minimize the whole 
         application. } 
        if shWindowVisible in SetupHeader.Options then 
         Application.Minimize 
        else 
         ShowWindow(WizardForm.Handle, SW_MINIMIZE); 
        end 
        else 
        if Message.CmdType and $FFF0 = SC_RESTORE then begin 
        if shWindowVisible in SetupHeader.Options then 
         Application.Restore 
        else 
         ShowWindow(WizardForm.Handle, SW_RESTORE); 
        end; 
        if Message.CmdType = 9999 then 
        MainForm.ShowAboutBox 
        else 
        inherited; 
    end; 
    

    Объявите новую процедуру под названиемTWizardForm.FormShow, как показано ниже:

    procedure FormShow(Sender: TObject); 
    

    Объявить его, как показано ниже в разделе Implementation мастера единицы.

    procedure TWizardForm.FormShow(Sender: TObject); 
    begin 
        if not(shWindowVisible in SetupHeader.Options) then 
        ShowWindow(Application.Handle, SW_HIDE); 
    end; 
    

    Наконец, добавьте TWizardForm.FormShow в OnShow Форма Событие WizardForm.

    Вы почти закончили! Теперь окно мастера должно отображать «Восстановить» и «Минимизировать анимацию», как вы ожидаете.

  3. Исправление проблемы MessageBox родительского окна после добавления Минимизации Transitions (анимация) в мастере установки Inno:

    Примечание: Это должно быть сделано, чтобы предотвратить Записано Мастер окна сообщений (Чей может отслеживаться с Inno Setup Compiler Log), иногда отображая две кнопки панели задач, даже WizardForm является видимым.

    В разделе { Variables for command line parameters } энергоблока Main, объявить новую булеву переменную как это:

    IsApplicationRunning: Boolean; 
    

    В автомагнитол Main,

    Изменить процедуруAbortInit, как это:

    procedure AbortInit(const Msg: TSetupMessageID); 
    begin 
        IsApplicationRunning := False; 
        LoggedMsgBox(SetupMessages[Msg], '', mbCriticalError, MB_OK, True, IDOK); 
        Abort; 
    end; 
    

    Изменить порядокAbortInitFmt1так:

    procedure AbortInitFmt1(const Msg: TSetupMessageID; const Arg1: String); 
    begin 
        IsApplicationRunning := False; 
        LoggedMsgBox(FmtSetupMessage(Msg, [Arg1]), '', mbCriticalError, MB_OK, True, IDOK); 
        Abort; 
    end; 
    

    Изменить порядокAbortInitServicePackRequiredтак:

    procedure AbortInitServicePackRequired(const ServicePack: Word); 
    begin 
        IsApplicationRunning := False; 
        LoggedMsgBox(FmtSetupMessage(msgWindowsServicePackRequired, ['Windows', IntToStr(Hi(ServicePack))]), '', mbCriticalError, MB_OK, True, IDOK); 
        Abort; 
    end; 
    

    В мастере единицы,

    Изменить ранее добавленный процедуруTWizardForm.FormShowтак:

    procedure TWizardForm.FormShow(Sender: TObject); 
    begin 
        if not(shWindowVisible in SetupHeader.Options) then 
        ShowWindow(Application.Handle, SW_HIDE); 
        IsApplicationRunning := True; 
    end; 
    

    В автомагнитол CmnFunc,

    Добавить Wizard и Main в разделе Uses в Implementation энергоблока CmnFunc.

    Изменить порядокAppMessageBoxтак:

    function AppMessageBox(const Text, Caption: PChar; Flags: Longint): Integer; 
    var 
        ActiveWindow: HWND; 
        MessageHandler: HWND; 
        WindowList: Pointer; 
    {$IFNDEF IS_D4} 
        DidMove: Boolean; 
        OldRect: TRect; 
    {$ENDIF} 
    begin 
        if MessageBoxRightToLeft then 
        Flags := Flags or (MB_RTLREADING or MB_RIGHT); 
    
        if IsApplicationRunning = False then 
        MessageHandler := Application.Handle 
        else 
        MessageHandler := WizardForm.Handle; 
    
        { If the application window isn't currently visible, show the message box 
        with no owner window so it'll get a taskbar button } 
        if IsIconic(MessageHandler) or (GetWindowLong(MessageHandler, GWL_STYLE) and WS_VISIBLE = 0) or (GetWindowLong(MessageHandler, GWL_EXSTYLE) and WS_EX_TOOLWINDOW <> 0) then begin 
        ActiveWindow := GetActiveWindow; 
        WindowList := DisableTaskWindows(0); 
        try 
         { Note: DisableTaskWindows doesn't disable invisible windows. 
         MB_TASKMODAL will ensure that Application.Handle gets disabled too. } 
         Result := MessageBox(0, Text, Caption, Flags or MB_TASKMODAL); 
        finally 
         EnableTaskWindows(WindowList); 
         SetActiveWindow(ActiveWindow); 
        end; 
        Exit; 
        end; 
    
        TriggerMessageBoxCallbackFunc(Flags, False); 
        try 
        {$IFDEF IS_D4} 
        { On Delphi 4+, simply call Application.MessageBox } 
        Result := Application.MessageBox(Text, Caption, Flags); 
        {$ELSE} 
        { Use custom implementation on Delphi 2 and 3. The Flags parameter is 
         incorrectly declared as a Word on Delphi 2's Application.MessageBox, and 
         there is no support for multiple monitors. } 
        DidMove := MoveAppWindowToActiveWindowMonitor(OldRect); 
        try 
         ActiveWindow := GetActiveWindow; 
         WindowList := DisableTaskWindows(0); 
         try 
         Result := MessageBox(Application.Handle, Text, Caption, Flags); 
         finally 
         EnableTaskWindows(WindowList); 
         SetActiveWindow(ActiveWindow); 
         end; 
        finally 
         if DidMove then 
         SetWindowPos(Application.Handle, 0, 
          OldRect.Left + ((OldRect.Right - OldRect.Left) div 2), 
          OldRect.Top + ((OldRect.Bottom - OldRect.Top) div 2), 
          0, 0, SWP_NOACTIVATE or SWP_NOREDRAW or SWP_NOSIZE or SWP_NOZORDER); 
        end; 
        {$ENDIF} 
        finally 
        TriggerMessageBoxCallbackFunc(Flags, True); 
        end; 
    end; 
    

    Теперь все Записан и любые другие окна сообщений будет отображаться нормально!

    Теперь, скомпилируйте программу установки (Setup.e32) с помощью Рекомендуемого компилятора в файле ReadMe и скопируйте его в каталог, в котором вы установили Inno Setup.

    Примечание. Установленная версия Unicode Inno Setup или Ansi должна соответствовать версии исходного кода Inno Setup, которую вы модифицировали для повторной компиляции. Или вы можете скомпилировать весь проект установки и копирования Inno - заменить эту измененную и повторно скомпилированную программу установки (Setup.e32) на каталог, в котором вы скомпилировали Inno Setup.

    После повторной компиляции программы установки вам необходимо добавить следующие коды к скрипту Pascal.

    [Files] 
    Source: "InnoCallback.dll"; Flags: dontcopy 
    
    [Code] 
    #ifdef UNICODE 
        #define AW "W" 
    #else 
        #define AW "A" 
    #endif 
    
    const 
        GWL_WNDPROC = -4; 
        SC_ABOUTBOX = 9999; 
        SC_RESTORE = $F120; 
        SC_MINIMIZE = $F020; 
        WM_SYSCOMMAND = $0112; 
    
    Type 
        WPARAM = UINT_PTR; 
        LPARAM = LongInt; 
        LRESULT = LongInt; 
        TWindowProc = function(hwnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; 
    
    var 
        PrevWndProc: LongInt; 
    
    function CallWindowProc(lpPrevWndFunc: LongInt; hWnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; 
        external 'CallWindowProc{#AW}@user32.dll stdcall'; 
    function WrapWindowProc(Callback: TWindowProc; ParamCount: Integer): LongWord; 
        external '[email protected]:InnoCallback.dll stdcall'; 
    function SetWindowLong(hWnd: HWND; nIndex: Integer; dwNewLong: LongInt): LongInt; 
        external 'SetWindowLong{#AW}@user32.dll stdcall'; 
    
    function Wizard_WMSYSCOMMAND(hwnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; 
    begin 
        if (uMsg = WM_SYSCOMMAND) and (wParam and $FFF0 = SC_MINIMIZE) then begin 
        //SOMETHING LIKE BASS_Pause();. 
        Log('Wizard Window has been Minimized.'); 
        end; 
        if (uMsg = WM_SYSCOMMAND) and (wParam and $FFF0 = SC_RESTORE) then begin 
        //SOMETHING LIKE BASS_Start();. 
        Log('Wizard Window has been Restored.'); 
        end; 
        if (uMsg = WM_SYSCOMMAND) and (wParam = SC_ABOUTBOX) then begin 
        Result := 0; 
        MainForm.ShowAboutBox; 
        end 
        else 
        Result := CallWindowProc(PrevWndProc, hwnd, uMsg, wParam, lParam); 
    end; 
    
    procedure InitializeWizard(); 
    begin 
        PrevWndProc := SetWindowLong(WizardForm.Handle, GWL_WNDPROC, WrapWindowProc(@Wizard_WMSYSCOMMAND, 4)); 
    end; 
    
    procedure DeinitializeSetup(); 
    begin 
        SetWindowLong(WizardForm.Handle, GWL_WNDPROC, PrevWndProc); 
    end; 
    

    Теперь, вы должны быть немедленно уведомлены, когда WizardForm Минимизирует или Восполнение через Compiler Сообщения журнала.Вы можете приостановить или возобновить музыку в соответствии с вашим кодом, добавив их в функцию Wizard_WMSYSCOMMAND.

+0

Это хорошо ..... Все в порядке! – Blueeyes789

+0

Мышление - это самый важный способ найти решение. ;-) – GTAVLover

+0

В 'Wizard_WMSYSCOMMAND' вы должны замаскировать' wParam' с помощью '$ FFF0', как и в' TWizardForm.WMSysCommand'. –