|
一个如影随形的小精灵会令到你的安装程序更加人性化. 就是这样一个功能的 Inno Setup 插件, 希望大家喜欢. ^_^ 注:插件在 Win2000 以上系统有效.向可爱的葱娘致敬. 特用了她来做例子.fairy.iss:; Inno Setup 精灵插件 ver 1.0 ; restools ; http://restools.hanzify.org [Files] Source: "fairy.dll"; Flags: dontcopy [code] type TCallbackProc = procedure(); // 精灵插件选项: // hParentWnd: 需要粘附的窗口句柄, 精灵会跟随这个窗口移动. // RelativePos: 精灵跟随窗口移动的相对位置. // 0: 以窗口左上角为原点, 所有制定的 X, Y 坐标都是相对于该原点的距离. // 1: 以窗口右上角为原点. // 2: 以窗口左下角为原点. // 3: 以窗口右下角为原点. // Interval: 每个图片更新的速度(时间间隔, 单位: ms). 用来微调动作的快慢. 但是动作演示的快慢主要还是由制定图片序列的时候处理, // 例如 100ms 下的更新速度是比较合理的, 也就是 1 秒钟更新 10 张图片. 所以在制定动作的时候以这个作为参考就好处理了. // ImgType: 图片处理类型. // 0: 带 Alpha 通道的 32bit 位图 Bitmap. // 推荐使用这种位图作为精灵显示, 因为这种位图跟 PNG 一样都有渐变透明的效果, // 重要的作用是可以令到透明部分和不透明部分之间的锯齿看起来比较平滑. // PNG 是经过压缩的, 所以 PNG 的载入需要一个解压的过程, 比 Alpha 32bit Bitmap 载入速度要慢. // 在压缩方面, 因为这是一个安装程序的插件, 所有文件都会经过压缩打包的, // 当你用 LZMA 压缩图片时, 你可以看见 Alpha 32bit Bitmap 压缩出来的安装程序比 PNG 的小很多. // 所以尽管在常规文件状态下 PNG 要比 BMP 小很多, 但是如果在安装程序的状态下情况就相反了, BMP 的反而比 PNG 的小很多. // 1: 普通 Bitmap, 不带通道. // 这种格式的处理, 必须指定透明颜色才能显示不规则的精灵形状, 比起带 Alpha 通道的 32bit Bitmap , 其弱点是明显的, // 例如渐变透明这种处理就不可能实现的了, 但是优点也是明显的, 就是压缩出来的安装包会很小, 因为毕竟 32bit 位图在转成 // 8bit 索引位图后在不压缩的情况下大小也会大幅减少, 而显示的颜色效果几乎没有损失. // 2: PNG 图片, 优点在于, 早期精灵制作的时候可以非常方便的处理, 因为处理上本人觉得要比带通道的 Bitmap 要易于处理. // TransparentColor: 透明颜色, 在 ImgType 为 1 的时候使用. function SetFairyOption(hParentWnd: HWND; RelativePos: Integer; Interval: Cardinal; ImgType, TransparentColor: Integer): Boolean; external 'SetFairyOption@files:fairy.dll stdcall'; // 添加图片到精灵插件中. // BmpFiles: 批量图片处理的序列. // 格式: X1|Y1|Alpha1|ImgFile1|X2|Y2|Alpha2|ImgFile2|X3|Y3|Alpha3|ImgFile3|......... // X: 相对于原点的水平坐标. // Y: 相对于原点的垂直坐标. // Alpha: 精灵的透明程度. // ImgFile: 图片文件. // FinishCallback: 因为批量添加大量图片可能会引起程序假死, 所以我采用线程处理, 所以在载入图片的过程中, 安装程序仍然可以同步运行. // 所以 FinishCallback 就是添加图片过程完成的时候调用的回调函数, 通常都是在这个函数中调用 AnimateFairy 来运行精灵. function AddImgsToList(BmpFiles: AnsiString; FinishCallback: TCallbackProc): Boolean; external 'AddImgsToList@files:fairy.dll stdcall'; // 添加图片到精灵插件中. // 属于单图片添加, 基本上这个函数只是给用户在程序中灵活运用而已, 上一函数已能完成此任务. // 参数请参看上一函数中的解释. function AddImgToList(X, Y: Integer; BlendAlpha: Byte; ImgFile: AnsiString): Boolean; external 'AddImgToList@files:fairy.dll stdcall'; // 清除图片序列中的所有图片. // 因为图片是顺序添加到序列中的, 所以如果需要重新排列图片, 必须清除所有图片, 重新添加. function ClearImgList(): Boolean; external 'ClearImgList@files:fairy.dll stdcall'; // 运行精灵, 也就是相当于序列图片的连续显示. // IndexList: 播放序列, 具体的使用方法请看以下几个例子. // 例子: // 0-53,(54-79) // 解释: 0 到 53 帧, 然后 54 到 79 帧循环播放, 无限循环, 不会结束, 也就是说不会触发 FinishCallback 事件. // 0-53,3(54-79) // 解释: 具体跟上一例子的差别是 54 到 79 帧循环播放 3 次后结束, 并调用 FinishCallback 回调函数. // 10-2,13,45,60,54,2(70-0),(50-70) // 解释: 10 到 2 帧倒序播放, 然后顺序显示 13,45,60,54 帧, 然后倒序循环播放 2 次 70 到 0 帧, 再然后无限循环播放 50 到 70 帧. // FinishCallback: 如果播放序列没有无限循环, 则在结束播放后, 就会调用这个回调函数. function AnimateFairy(IndexList: AnsiString; FinishCallback: TCallbackProc): Boolean; external 'AnimateFairy@files:fairy.dll stdcall'; // 停止播放. function StopFairy(): Boolean; external 'StopFairy@files:fairy.dll stdcall'; // 显示并恢复播放. function ResumeFairy(): Boolean; external 'ResumeFairy@files:fairy.dll stdcall'; // 隐藏并停止播放. function HideFairy(): Boolean; external 'HideFairy@files:fairy.dll stdcall'; // 显示精灵. function ShowFairy(): Boolean; external 'ShowFairy@files:fairy.dll stdcall'; // 显示某一帧的精灵. function ShowFairyEx(ImgIndex: Integer): Boolean; external 'ShowFairyEx@files:fairy.dll stdcall'; // 精灵虽然会显示在主窗口的上面, 但是并不会遮挡鼠标的操作, 即使精灵下有一个按钮, 鼠标仍然可以穿透精灵点击后面的按钮. // 但是对于非主窗口的其他窗口, 鼠标操作并不能穿透. Example.iss:#include "fairy.iss" // 这是一个令到你的安装程序更加人性化的 Inno Setup 插件. // 注释或取消注释下面的 ImgType 定义, 可以选择不同的图片处理方法作为精灵插件的处理. // 具体图片处理的区别请参阅 fairy.iss 函数定义中的解释. #define ImgType 0 //#define ImgType 1 //#define ImgType 2 [Setup] AppName=fairy AppVerName=fairy Ver 1.0 DefaultDirName={pf}\fairy DefaultGroupName=fairy OutputDir=userdocs:Inno Setup Examples Output OutputBaseFilename=setup_{#ImgType} SolidCompression=yes [Files] #if ImgType == 0 ; 带 Alpha 通道的 32bit 位图 Bitmap Source: "bmp_32bit_Alpha\*.bmp"; Flags: dontcopy #elif ImgType == 1 ; 普通位图 Bitmap Source: "bmp\*.bmp"; Flags: dontcopy #elif ImgType == 2 ; PNG Source: "png\*.png"; Flags: dontcopy #endif [code] function GetSystemMetrics(nIndex: Integer): Integer; external 'GetSystemMetrics@user32.dll stdcall'; const SM_CYBORDER = 6; SM_CYDLGFRAME = 8; procedure FinishPlayCallback(); begin MsgBox('FinishPlay', mbInformation, MB_OK); end; procedure PlayListCallback2(); begin AnimateFairy('0-53,2(54-79)', @FinishPlayCallback); end; procedure PlayListCallback(); begin // ShowFairyEx(10); AnimateFairy('0-53,(54-79)', nil); end; procedure BtnOnClick(Sender: TObject); var i, BAlpha: Integer; x, y: Integer; ImgFile: AnsiString; S: AnsiString; BH: Integer; begin SetFairyOption(WizardForm.Handle, TNewButton(Sender).Tag, 100, {#ImgType}, clFuchsia); ClearImgList; S := ''; BH := GetSystemMetrics(SM_CYBORDER) + GetSystemMetrics(SM_CYDLGFRAME); if TNewButton(Sender).Caption = '4' then begin x := 180; y := -88-BH; end else case TNewButton(Sender).Tag of 0: begin x := 80; y := -88; end; 1: begin x := -170; y := -88; end; 2: begin x := 80; y := -88-BH; end; 3: begin x := -170; y := -88-BH; end; end; BAlpha := 30; for i := 0 to 7 do begin #if ImgType == 2 ImgFile := format('%.2d',[i+1])+'.png'; #else ImgFile := format('%.2d',[i+1])+'.bmp'; #endif ExtractTemporaryFile(ImgFile); if S <> '' then S := S + '|'; S := S + IntToStr(x) + '|' + IntToStr(y) + '|' + IntToStr(BAlpha) + '|' + ExpandConstant('{tmp}\'+ImgFile); BAlpha := BAlpha + 30; end; for i := 8 to 79 do begin #if ImgType == 2 ImgFile := format('%.2d',[i+1])+'.png'; #else ImgFile := format('%.2d',[i+1])+'.bmp'; #endif ExtractTemporaryFile(ImgFile); if S <> '' then S := S + '|'; S := S + IntToStr(x) + '|' + IntToStr(y) + '|' + IntToStr(255) + '|' + ExpandConstant('{tmp}\'+ImgFile); end; if TNewButton(Sender).Caption = '4' then AddImgsToList(S, @PlayListCallback2) else AddImgsToList(S, @PlayListCallback); end; procedure InitializeWizard(); var Btn: TNewButton; begin WizardForm.BorderIcons := [biSystemMenu,biMinimize,biMaximize]; WizardForm.BorderStyle := bsSizeable; WizardForm.WelcomeLabel2.Caption := '尝试改变窗口大小, 可以测试精灵插件对于窗口的相对位置的效果.'+#13#10 '按钮1: 以窗口左上角做原点. 0-53,(54-79) 无限循环.'+#13#10 '按钮2: 以窗口右上角做原点. 0-53,(54-79) 无限循环.'+#13#10 '按钮3: 以窗口左下角做原点. 0-53,(54-79) 无限循环.'+#13#10 '按钮3: 以窗口右下角做原点. 0-53,(54-79) 无限循环.'+#13#10 '按钮4: 以窗口左下角做原点. 0-53,2(54-79) 循环 2 次结束.'; with TNewButton.Create(WizardForm) do begin Parent := WizardForm.WelcomePage; SetBounds(ScaleX(216), ScaleY(207), ScaleX(19), ScaleY(23)); Caption := '0'; Tag := 0; OnClick := @BtnOnClick; end; Btn := TNewButton.Create(WizardForm); with Btn do begin Parent := WizardForm.WelcomePage; SetBounds(ScaleX(240), ScaleY(207), ScaleX(19), ScaleY(23)); Caption := '1'; Tag := 1; OnClick := @BtnOnClick; end; with TNewButton.Create(WizardForm) do begin Parent := WizardForm.WelcomePage; SetBounds(ScaleX(264), ScaleY(207), ScaleX(19), ScaleY(23)); Caption := '2'; Tag := 2; OnClick := @BtnOnClick; end; with TNewButton.Create(WizardForm) do begin Parent := WizardForm.WelcomePage; SetBounds(ScaleX(288), ScaleY(207), ScaleX(19), ScaleY(23)); Caption := '3'; Tag := 3; OnClick := @BtnOnClick; end; with TNewButton.Create(WizardForm) do begin Parent := WizardForm.WelcomePage; SetBounds(ScaleX(368), ScaleY(207), ScaleX(19), ScaleY(23)); Caption := '4'; Tag := 2; OnClick := @BtnOnClick; end; BtnOnClick(Btn); end; procedure DeinitializeSetup(); begin HideFairy; WizardForm.Hide; end; 下载地址: http://restools.hanzify.org/inno/InnoFairy/InnoFairy(7zip)_ver1.0.zip [ 此帖被restools在2010-09-25 19:12重新编辑 ]
|