Inno setup Inno安装程序在WizardForm最小化和恢复时检测(获得通知)

Inno setup Inno安装程序在WizardForm最小化和恢复时检测(获得通知),inno-setup,pascalscript,Inno Setup,Pascalscript,我正在我的Pascal脚本中添加一个低音音频项目。为长时间安装添加音乐播放对用户来说并不坏。但当用户将向导窗体最小化到任务栏时,最好停止音乐。如果用户再次从任务栏恢复音乐,则自动启动音乐 我想知道如何检测WizardForm是否最小化或恢复,并根据WizardForm的窗口状态暂停或启动低音音乐播放。使用诸如低音暂停、低音停止或低音启动等功能 我应该选择怎样做,做什么?TWindowState还是WMSYSCOMMAND 提前感谢。我认为当向导窗体最小化或还原时,不会有任何事件通知您。TForm

我正在我的Pascal脚本中添加一个低音音频项目。为长时间安装添加音乐播放对用户来说并不坏。但当用户将向导窗体最小化到任务栏时,最好停止音乐。如果用户再次从任务栏恢复音乐,则自动启动音乐

我想知道如何检测WizardForm是否最小化或恢复,并根据WizardForm的窗口状态暂停或启动低音音乐播放。使用诸如低音暂停、低音停止或低音启动等功能

我应该选择怎样做,做什么?TWindowState还是WMSYSCOMMAND


提前感谢。

我认为当向导窗体最小化或还原时,不会有任何事件通知您。TForm.WindowsState在Inno Setup Pascal脚本中也不可用

但是您可以安排一个频繁的计时器并检查表单状态的变化

请注意,表单实际上是隐藏的,而不是最小化的,当您单击“最小化”按钮时,没有最小化动画。因此,请使用检查WS_可见窗口样式

[守则] 常数 GWL_风格=-16; WS_VISIBLE=$10000000; 函数GetWindowLonghWnd:THandle;nIndex:Integer:LongInt; 外部的GetWindowLongW@User32.dllstdcall'; 函数设置计时器 hWnd:长单词;nIDEvent,UEFalse:长单词;lpTimerFunc:LongWord:LongWord; 外部的SetTimer@user32.dllstdcall'; 变量 瓦希登:布尔; 程序HiddenTimerProcH:LongWord;味精:长词;IdEvent:长单词;时间:长词; 变量 隐藏:布尔; 花柱:长; 开始 样式:=GetWindowLongWizardForm.Handle,GWL_样式; 隐藏:=样式,WS_可见=0; 如果是隐藏的而不是隐藏的,那么 开始 记录“最小化,停止音乐…”; 终止 其他的 如果没有隐藏和隐藏,那么 开始 日志“已恢复,正在恢复音乐…”; 终止 WasHidden:=隐藏; 终止 程序初始化; 开始 瓦希登:=假; SetTimer0,0500,CreateCallback@HiddenTimerProc; 终止
对于,您需要Inno设置6。如果您坚持使用Inno Setup 5,您可以使用库中的WrapCallback函数。

不幸的是,没有任何通知事件可以通知您WizardForm是否最小化或恢复,因为构建安装不需要此类事件

如果确实要检查WizardForm是否已还原或最小化,而不是检查其可见性

首先,您需要修改Inno Setup源代码,为向导窗口提供最小化和还原转换动画

注意:以下源代码更改已在Inno Setup 5.5.9 Unicode和Ansi版本中成功测试

从Inno Setup的安装程序中完全隐藏Delphi的隐藏应用程序表单:

Setup.exe>Setup.exe的项目选项>应用程序>目标文件扩展名>e32

右键单击Setup.e32>查看源

更改设置程序的{初始化…部分,如下所示:

如果ShWindow在SetupHeader.Options中可见,则在ShowWindowApplication.Handle、SW_SHOW;行之前添加

按如下方式更改安装程序的{Run}部分:

... {Run} 尝试 Application.MainFormOnTaskBar:=False; Application.ShowMainForm:=False; ShowWindowApplication.Handle、SW_隐藏; 应用程序。运行; 除了 ... 你完成了!现在它将被隐藏

有关背景信息,请参阅

将最小化和还原过渡动画添加到Inno安装向导窗体:

在单元向导中

更改TWizardForm.CreateParams如下:

过程TWizardForm.CreateParamsvar参数:TCreateParams; 开始 继承; {通过设置MainForm,确保窗体位于MainForm之上 当*MainForm设置为Visible*}时窗体的父级 如果ShWindow在SetupHeader.Options中可见,则 Params.WndParent:=MainForm.Handle 其他的 Params.WndParent:=GetDesktopWindow; 终止 更改TWizardForm.WMSysCommand如下:

过程TWizardForm.WMSysCommandvar消息:TWMSysCommand; 开始 如果Message.CmdType和$FFF0=SC\u最小化,则开始 {当SHWindow在中可见时,向导窗体上会显示最小化按钮 SetupHeader.Options。单击它时,我们希望最小化整个 应用程序} 如果ShWindow在SetupHeader.Options中可见,则 应用程序。最小化 其他的 ShowWindowWizardForm.Handle,SW_最小化; 终止 其他的 如果Message.CmdType和$FFF0=SC\u RESTORE,则开始 如果ShWindow在SetupHeader.Options中可见,则 应用程序恢复 其他的 ShowWindowWizardForm.Handle,软件恢复; 终止 如果Message.CmdType=9999,则 MainForm.ShowAboutBox 其他的 继承; 终止 声明一个名为TWizardForm.FormShow的新过程,如下所示:

程序表单显示发送方:TObject; 在“单元向导”的“实现”部分中声明它,如下所示

程序TWizardForm.FormShowSender:ToObject; 开始 如果SetupHeader中的NotshWindow可见。选项则 ShowWindowApp 应用。手柄,开关隐藏; 终止 最后,将这个TWizardForm.FormShow添加为WizardForm的OnShow表单事件

你差不多完了!现在,向导窗口应该显示恢复和最小化动画,正如您所期望的那样

将最小化转换动画添加到Inno安装向导后,修复MessageBox父窗口问题:

注意:必须这样做,以防止可以使用Inno安装编译器日志记录的已记录向导消息框有时显示两个任务栏按钮,即使向导窗体可见

在Unit Main的{Variables for command line parameters}部分中,声明一个新的布尔变量,如下所示:

IsApplicationRunning:布尔值; 在主要单元中

将过程更改为如下所示:

过程中止常量消息:TSetupMessageID; 开始 IsApplication Running:=假; LoggedMsgBoxSetupMessages[Msg],mbCriticalError,MB_OK,True,IDOK; 中止 终止 按如下方式更改过程FMT1:

过程中止FMT1CONST消息:TSetupMessageID;常量Arg1:字符串; 开始 IsApplication Running:=假; LoggedMsgBoxFmtSetupMessageMsg[Arg1],mbCriticalError,MB_OK,True,IDOK; 中止 终止 按以下方式更改所需的过程:

过程中止ServicePackRequiredConst ServicePack:Word; 开始 IsApplication Running:=假; LoggedMsgBoxFmtSetupMessagemsgWindowsServicePackRequired,['Windows',IntToStrHiServicePack],mbCriticalError,MB_OK,True,IDOK; 中止 终止 在单元向导中

修改之前添加的TWizardForm.FormShow过程,如下所示:

程序TWizardForm.FormShowSender:ToObject; 开始 如果SetupHeader中的NotshWindow可见。选项则 ShowWindowApplication.Handle、SW_隐藏; IsApplication Running:=真; 终止 单位为CmnFunc

将向导和Main添加到单元CmnFunc实现中的Uses部分

按如下方式更改过程AppMessageBox:

函数AppMessageBoxconst Text,标题:PChar;标志:Longint:整数; 变量 活动窗口:HWND; MessageHandler:HWND; 窗口列表:指针; {$IFNDEF是_D4} DidMove:布尔; OldRect:TRect; {$ENDIF} 开始 如果MessageBoxRightToLeft,则 标志:=标志或MB_RTLREADING或MB_RIGHT; 如果IsApplicationRunning=False,则 MessageHandler:=应用程序.句柄 其他的 MessageHandler:=WizardForm.Handle; {如果应用程序窗口当前不可见,请显示消息框 没有所有者窗口,因此它将获得一个任务栏按钮} 如果IsIconicMessageHandler或GetWindowLongMessageHandler、GWL_STYLE和WS_VISIBLE=0或GetWindowLongMessageHandler、GWL_EXSTYLE和WS_EX_TOOLWINDOW 0,则开始 ActiveWindow:=GetActiveWindow; WindowList:=DisableTaskWindows0; 尝试 {注意:DisableTaskWindows不会禁用不可见的窗口。 MB_taskmodel将确保Application.Handle也被禁用。} 结果:=MessageBox0、文本、标题、标志或MB_TASKMODAL; 最后 启用任务窗口窗口列表; 设置活动窗口活动窗口; 终止 出口 终止 TriggerMessageBoxCallbackFuncFlags,False; 尝试 {$IFDEF是_D4} {在Delphi4+上,只需调用Application.MessageBox} 结果:=Application.MessageBoxText、标题、标志; {$ELSE} {在Delphi 2和Delphi 3上使用自定义实现。Flags参数为 在Delphi 2的Application.MessageBox上错误地声明为Word,并且 不支持多个监视器。} DidMove:=移动AppWindow以激活Windows监视器或LDRECT; 尝试 ActiveWindow:=GetActiveWindow; WindowList:=DisableTaskWindows0; 尝试 结果:=MessageBoxApplication.Handle、文本、标题、标志; 最后 启用任务窗口窗口列表; 设置活动窗口活动窗口; 终止 最后 如果我搬家的话 SetWindowPosApplication.Handle,0, OldRect.Left+OldRect.Right-OldRect.Left第2部分, OldRect.Top+OldRect.Bottom-OldRect.Top第2部分, 0,0,SWP_NOACTIVE或SWP_NOREDRAW或SWP_NOSIZE或SWP_NOZORDER; 终止 {$ENDIF} 最后 TriggerMessageBoxCallbackFuncFlags,True; 终止 终止 现在所有记录的和任何其他消息框都将正常显示

现在,使用自述文件中推荐的编译器编译安装程序Setup.e32,并将其复制到安装Inno Setup的目录中

注意:Inno Setup Unicode或Ansi的安装版本必须与您修改以重新编译的Inno Setup的源代码版本相匹配。或者,您可以编译整个Inno安装项目,并将此修改和重新编译的安装程序Setup.e32复制-替换到编译Inno安装程序的目录中

重新编译安装程序后,需要向Pascal脚本添加以下代码

[档案] 来源:InnoCallback.dll;标志:dontcopy [守则] ifdef UNICODE 定义AW W 其他的 定义AWA 恩迪夫 常数 GWL_WNDPROC=-4; SC_ABOUTBOX=9999; SC_还原=$F12 0; SC_最小化=$F020; WM_SYSCOMMAND=$0112; 类型 WPARAM=UINT_PTR; LPARAM=长型; LRESULT=LongInt; TWindowProc=函数HWND:HWND;uMsg:UINT;wParam:wParam;lParam:lParam:LRESULT; 变量 PrevWndProc:LongInt; 函数CallWindowProclpPrevWndFunc:LongInt;hWnd:hWnd;Msg:UINT;wParam:wParam;lParam:lParam:LRESULT; 外部“CallWindowProc{AW}@user32.dll stdcall”; 函数WrapWindowProcCallback:TWindowProc;ParamCount:整数:长字; 外部的wrapcallback@files:InnoCallback.dll stdcall'; 函数SetWindowLonghWnd:HWND;nIndex:整数;dwNewLong:LongInt:LongInt; 外部“SetWindowLong{AW}@user32.dll stdcall”; 函数向导\u WMSYSCOMMANDhwnd:HWND;uMsg:UINT;wParam:wParam;lParam:lParam:LRESULT; 开始 如果uMsg=WM_SYSCOMMAND和wParam且$FFF0=SC_最小化,则开始 //类似于BASS_Pause;。 日志“向导窗口已最小化”; 终止 如果uMsg=WM_SYSCOMMAND和wParam且$FFF0=SC_RESTORE,则开始 //类似于BASS_Start;。 记录“向导窗口已还原”; 终止 如果uMsg=WM_SYSCOMMAND和wParam=SC_ABOUTBOX,则开始 结果:=0; main form.ShowAboutBox; 终止 其他的 结果:=CallWindowProcPrevWndProc、hwnd、uMsg、wParam、lParam; 终止 程序初始化; 开始 PrevWndProc:=SetWindowLongWizardForm.Handle,GWL_WNDPROC,WrapWindowProc@Wizard_WMSYSCOMMAND4. 终止 程序去初始化设置; 开始 SetWindowLongWizardForm.Handle,GWL_WNDPROC,PrevWndProc; 终止 现在,当WizardForm通过编译器日志消息最小化或还原时,应该立即通知您。您可以根据代码暂停或恢复音乐,方法是将它们添加到函数向导\u WMSYSCOMMAND中


认真思考是找到解决办法的最重要方法-在向导\u WMSYSCOMMAND中,您应该使用$FFF0屏蔽wParam,就像在TWizardForm.WMSYSCOMMAND中一样。您的意思是像wParam=$FFF0和SC\u一样最小化?如果不是,它应该是怎样的?没有wParam和$FFF0=SC_现在就最小化了吗?而且我没有注意到改变后有什么特别的。为什么要像你说的那样改变?