NSIS进阶教程(四)

来源:互联网 发布:大数据建模工程师 编辑:程序博客网 时间:2024/05/01 17:40

NSIS进阶教程(四)

自定义目录选择,自定义进度条,自定义图片切换效果

**前言**

上一节中我们已经处理了有关CheckBox自定义贴图的部分,但是目录选择的部分还没有加上,这节,我们先处理一下目录的选择部分,选择完路径之后就剩下安装了,于是进度条的创建的显得很有必要,但是系统的进度条创建简单,如何改变进度条的背景色跟进度色呢,这节我们也处理掉。有关图片切换的效果的插件也有很多,但是大部分都是基于默认安装窗体进行的,如何在一个完全自定义的页面上面创建一个图片切换效果呢,这节也可以得到答案。

本篇主要讲讲以下几点:

  1. 创建目录选择按钮与文本框

  2. 创建自定义的进度条

  3. 创建图片切换效果

所用到的插件【新增】:

  • WebCtrl

  • SkinProgress

  • BgWorker

**讲义**

首先贴出今天教程的完整的例子【已测试】【附带图片】 猛击这里

这次的教程基本是安装界面的最后的阶段的处理了,主要是创建一个目录选择控件,用于确定安装程序安装的路径,在安装过程中等待时间也是比较长的,遇到打广告的好时机不要错过,切换多图是个不错的选择;在安装过程中,释放文件是一个主要动作。如果不是自定义页面,该动作是在系统的安装页面的Section里面完成的,如果不做多线程处理,该动作会阻塞主线程也就是主界面的消息传递,主界面没有了消息传递也就不会响应拖动、点击关闭等等操作,这个是本节主要说明的地方。最后说一下图片切换的实现,以我目前尝试的,效果最好的还算是直接放一张网页最实在,通过网页的js实现切换效果。

  1. 目录选择框

    目录选择框包括一个文本框跟一个Button按钮,做过Web的人都知道,html中有一个file的控件与之相吻合,在form中则是两个不同的component,文本框很好创建,按钮的单击事件是一个重点,我们看看代码:

    ;更改目录控件创建    ${NSD_CreateDirRequest} 26 79 358 25 "$INSTDIR"    Pop $Txt_Browser    ${NSD_OnChange} $Txt_Browser OnChange_DirRequest                                                                                                                                                                            ${NSD_CreateBrowseButton} 400 79 88 25 ""    Pop $Btn_Browser    StrCpy $1 $Btn_Browser    Call SkinBtn_Browser    GetFunctionAddress $3 OnClick_BrowseButton      SkinBtn::onClick $1 $3

    这里创建了一个$Txt_Browser的文本框,一个$Btn_Browser的按钮,其中按钮的单击事件是 OnClick_BrowserButton,看看按钮的事件代码:

    Function OnClick_BrowseButton  Pop $0                                                                                                                                                                   Push $INSTDIR   Call GetParent  Pop $R0                                                                                                                                                                   Push $INSTDIR  Push "\"  Call GetLastPart  Pop $R1                                                                                                                                                                   nsDialogs::SelectFolderDialog "请选择 $R0 安装的文件夹:" "$R0"  Pop $0  ${If} $0 == "error"     Return  ${EndIf}  ${If} $0 != ""    StrCpy $INSTDIR "$0\$R1"    system::Call `user32::SetWindowText(i $Txt_Browser, t "$INSTDIR")`  ${EndIf}FunctionEnd                                                                                                                                                            ;得到选中目录用于拼接安装程序名称Function GetParent  Exch $R0  Push $R1  Push $R2  Push $R3  StrCpy $R1 0  StrLen $R2 $R0  loop:    IntOp $R1 $R1 + 1    IntCmp $R1 $R2 get 0 get    StrCpy $R3 $R0 1 -$R1    StrCmp $R3 "\" get    Goto loop  get:    StrCpy $R0 $R0 -$R1    Pop $R3    Pop $R2    Pop $R1    Exch $R0FunctionEnd                                                                                                                                                                                                                                                                                                                            ;截取选中目录Function GetLastPart  Exch $0 ; chop char  Exch  Exch $1   Push $2  Push $3  StrCpy $2 0  loop:    IntOp $2 $2 - 1    StrCpy $3 $1 1 $2    StrCmp $3 "" 0 +3      StrCpy $0 ""      Goto exit2    StrCmp $3 $0 exit1    Goto loop  exit1:    IntOp $2 $2 + 1    StrCpy $0 $1 "" $2  exit2:    Pop $3    Pop $2    Pop $1    Exch $0 FunctionEnd

    单击按钮的时候用nsDialogs创建一个SelectFolderDialog的对话框,选择需要安装的路径。GetParent方法主要是要取得当前选中的路径,GetLastPart主要是保留当前的安装程序最底层的目录名称,最终两个部分合起来作为整体的安装路径赋值给$INSTDIR。具体的效果可以运行源码查看。             

  2. 创建自定义进度条

    nsDialogs有自带的进度条,该进度条的颜色是那种系统的颜色,如果遇到自己设计的,就会出现问题,于是用SkinProgress就可以给进度条赋上两张图片,一张是底图,一张是进度图,虽然不是非常的完美,比如圆角,比如透明,比如阴影,比如……但是已经是跟NSIS快捷脚本配合的很好的了。

    ${NSD_CreateProgressBar} 24 265 474 7 ""    Pop $PB_ProgressBar    SkinProgress::Set $PB_ProgressBar "$PLUGINSDIR\loading2.bmp" "$PLUGINSDIR\loading1.bmp"

    用法非常简单,用nsDialogs创建一个ProgressBar,然后用SkinProgress去set一下,后面跟上两张图片。ProgressBar的图片是有讲究的,具体的可以看源码的image文件夹中两张图片的切图,基本要使用什么效果,自己做两张图就可以了。                           

  3. 创建图片切换

    图片的切换有很多种,gif、flash、js、甚至自己用c++做插件实现,这里提供一种很方面,但是又不失功能强大的方式。网页的形式!你很容易能自己写一段js实现多张图片的切换,这里唯一要解决的就是如何在Form上创建一个浏览器用于加载自己的本地html页面。

    System::Call `*(i,i,i,i)i(1,34,518,200).R0`    System::Call `user32::MapDialogRect(i$HWNDPARENT,iR0)`    System::Call `*$R0(i.s,i.s,i.s,i.s)`    System::Free $R0    FindWindow $R0 "#32770" "" $HWNDPARENT    System::Call `user32::CreateWindowEx(i,t"STATIC",in,i${DEFAULT_STYLES}|${SS_BLACKRECT},i1,i34,i518,i200,iR0,i1100,in,in)i.R0`    StrCpy $WebImg $R0    WebCtrl::ShowWebInCtrl $WebImg "$PLUGINSDIR/index.htm"

    首先在界面上创建一个STATIC的对象(对话框),通过MapDialogRect来定位该对话框的位置(1,34),大小(518,200),然后通过WebCtrl控件来把自己的网页index.htm加载进去,WebCtrl插件实现的就是调用本地浏览器。这里定位浏览器的位置以及大小是难点,还需多多熟悉才是。

    网页里面的代码我就不讲解了,主要是图片js切换,你也可以更换js代码,网络中很多效果都有。

    如果发现界面上的图片切换画面跟外边框有距离,就去查看网页里面的css,是否把margin跟padding都设成了0,这样就没有间隙了,看上去跟贴在form上面的一样。:)                                     

  4. 多线程安装

    界面都画好了,现在说到安装文件的时候释放了。源码中我是通过sleep来模拟的,具体的释放跟这个差不多。首先创建的是一个只运行一次的定时器Timer:

    GetFunctionAddress $0 NSD_TimerFun    nsDialogs::CreateTimer $0 1

    其中nsDialogs::CreateTimer后面的参数1代表的是1毫秒,正常情况下就是1毫秒执行一次NSD_TimerFun介个方法。

    Function NSD_TimerFun    GetFunctionAddress $0 NSD_TimerFun    nsDialogs::KillTimer $0    !if 1   ;是否在后台运行,1有效        GetFunctionAddress $0 InstallationMainFun        BgWorker::CallAndWait    !else        Call InstallationMainFun    !endifFunctionEnd

    本身定时器就是一个异步的功能,如果定时器是同步的,那就没有意义了对不,那么既然是异步的,为什么在NSD_TimerFun里面做Sleep操作的时候,主界面会卡死不响应呢。这个就要看看nsDialogs插件如何实现这个定时器的了,我也没有详查,应该不是创建子线程Thread 的方式。

    这里如果抛弃Timer,直接使用BgWorker的话,也可以,但是会有一个缺陷:当你需要同时运行两个方法的时候,只有通过创建两个Timer来实现,并且在Timer调用的方法里面采用BgWorker来实现子线程操作。

    看看上面代码在Timer执行方法里面,第一步是停止Timer:因为我们只用了他的异步的特点,并没有想做定时器。然后使用BgWorker插件。

    使用BgWorker插件非常简单,只需用$0接收方法地址,然后调用BgWorker::CallAndWait。顾明思意,BgWorker调用过程是同步的,而且会Wait到InstallationMainFun方法执行结束,如果BgWorker::CallAndWait调用下面还有代码的话,只有在执行完InstallationMainFun方法后才能执行。

    下面看看InstallationMainFun的实现:

    Function InstallationMainFun    SendMessage $PB_ProgressBar ${PBM_SETRANGE32} 0 100    SendMessage $PB_ProgressBar ${PBM_SETPOS} 10 0    Sleep 1000    SendMessage $PB_ProgressBar ${PBM_SETPOS} 20 0    Sleep 1000    SendMessage $PB_ProgressBar ${PBM_SETPOS} 30 0    Sleep 1000    SendMessage $PB_ProgressBar ${PBM_SETPOS} 40 0    Sleep 1000    SendMessage $PB_ProgressBar ${PBM_SETPOS} 50 0    Sleep 1000    SendMessage $PB_ProgressBar ${PBM_SETPOS} 60 0    Sleep 1000    SendMessage $PB_ProgressBar ${PBM_SETPOS} 70 0    Sleep 1000    SendMessage $PB_ProgressBar ${PBM_SETPOS} 80 0    Sleep 1000    SendMessage $PB_ProgressBar ${PBM_SETPOS} 90 0    Sleep 1000    SendMessage $PB_ProgressBar ${PBM_SETPOS} 100 0                                       ShowWindow $Btn_Next ${SW_SHOW}    ShowWindow $Btn_Install ${SW_HIDE}    EnableWindow $Btn_Cancel 0FunctionEnd

    所做的工作主要是操作滚动条的位置。在实际的释放过程中,这个设置也是这样的,目前还没有自定义页面的释放插件,能回调得到精确的释放量,以及释放文件等等信息。所以只能模拟,尽可能的细化下来,估计着大概多少。这个是一个需要情商的工作,如果你有洁癖,偏执之类的病,我想你还是用系统自带的释放好了,也不需要自定义页面了 。

    最后上几张图吧,好看点,也算是阶段的结束 。

    (安装过程)

    (安装过程结束)

    (安装结束)

     

**结束语**

四节的自定义教程也就到此为止了,日后会补充一些技巧性的东西,也准备搞搞,修修插件,发布发布。That's all,Thanx!       

0 0
原创粉丝点击