NSIS进阶教程(三)自定义MessageBox,自定义页跳转,自定义CheckBox样式前言

本篇主要讲讲以下几点:

  • 如何抛弃系统的MessageBox

  • 如何实现自定义页面的跳转

  • 如何用自己的贴图实现CheckBox功能

所用到的插件【新增】:

  • FindProcDLL(查找当前进程插件)

  • KillProcDLL (关闭指定进程插件)

讲义

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

题外话,本节的重点是如何把系统的MessageBox替换掉自定义的窗口,一开始这个命题挺难的,原本因为nsDialogs可以创建一个弹窗,然后给它披上一层皮就可以了,在查了很多资料后,我了解到根本不行,nsDialogs插件不能完成这么简单的工作,而是通过另一个插件nsWindows来完成。另一个自定义CheckBox功能还是有点讨巧的,其实在窗体编程中,Button跟CheckBox本质上是一样的东西,CheckBox就是Button披上一层皮加上一些单击事件改变皮肤而存在的,于是就有了CheckBox的自定义的可能性。

还是要讲一点不足,此处CheckBox不包含旁边的说明文字,也就是说,当你促发CheckBox旁边的文字某些事件的时候CheckBox本事不会有任何反应,这样就不能构成一个CheckBox的整体,不过对于要求不是非常高的人来说,这点完全可以忽略。

如何抛弃系统的MessageBox

通常在使用警告框的时候,我们会调用MessageBox的NSIS命令,然而此窗口无比丑陋,简直是对我们正在做的窗体的亵渎。于是我们自己创建警告框,此警告框也要跟我们已有的窗口风格一致,包含几大问题,“无边框”、“美观贴图”、“移动”、“逻辑判断功能”,做到以上几点就可以了。上代码:

Function onCancel
 IsWindow $WarningForm Create_End
 !define Style ${WS_VISIBLE}|${WS_OVERLAPPEDWINDOW}
 ${NSW_CreateWindowEx} $WarningForm $hwndparent ${ExStyle} ${Style} "" 1018

 ${NSW_SetWindowSize} $WarningForm 349 184
 EnableWindow $hwndparent 0
 System::Call `user32::SetWindowLong(i$WarningForm,i${GWL_STYLE},0x9480084C)i.R0`
 ${NSW_CreateButton} 148 122 88 25 ''
 Pop $R0
 StrCpy $1 $R0
 Call SkinBtn_Quit
 ${NSW_OnClick} $R0 OnClickQuitOK

 ${NSW_CreateButton} 248 122 88 25 ''
 Pop $R0
 StrCpy $1 $R0
 Call SkinBtn_Cancel
 ${NSW_OnClick} $R0 OnClickQuitCancel

 ${NSW_CreateBitmap} 0 0 100% 100% ""
 Pop $BGImage
 ${NSW_SetImage} $BGImage $PLUGINSDIR\quit.bmp $ImageHandle
 GetFunctionAddress $0 onWarningGUICallback
 WndProc::onCallback $BGImage $0 ;处理无边框窗体移动
 ${NSW_CenterWindow} $WarningForm $hwndparent
 ${NSW_Show}
 Create_End:
 ShowWindow $WarningForm ${SW_SHOW}
FunctionEnd

这个onCancel方法是在我们在主窗体上点击“取消”或者“关闭”的时候促发的方法,这时会弹出一个命令窗口出来。

创建跟设置样式:WS_VISIBLE 是显示的意思,不加会隐藏掉,WS_OVERLAPPEDWINDOW 是创建一个层叠窗体的属性也需要加上。NSW_CreateWindowEx 是创建窗体的主命令。

创建完窗体后,用NSW_SetWindowSize 更改一下窗体的大小。

EnableWindow $hwndparent 0这段代码一定要加上,这是创建一个警告框模式窗体的必要条件,就是让主窗体不能操作。

接下来就是消除边框,用nsWindows命令创建按钮的一套,跟nsDialogs的创建是一致的,包括无边框移动的一套,在第一节中已经讲过,这里就不啰嗦了。

最后把这个窗体展示出来就可以了。把这个onCancel这个方法赋给“取消”按钮的单击事件,这样一个无边框模式窗体警告框就好了。

当我们点击“退出”的时候,就要关掉当前程序,所以要添加一个关闭的方法:

Function onClickClose
 FindProcDLL::FindProc "test.exe"
 Sleep 500
 Pop $R0
 ${If} $R0 != 0
 KillProcDLL::KillProc "test.exe"
 ${EndIf}
FunctionEnd

通过FindProcDLL插件的FindProc方法找到安装进程,并且通过KillProcDLL插件的KillProc杀之。

当我们点击“取消”的时候,这时候需要关闭当前警告框,并且让主窗体能够处于Active状态

Function OnClickQuitCancel
 ${NSW_DestroyWindow} $WarningForm
 EnableWindow $hwndparent 1
 BringToFront
FunctionEnd

NSW_DestroyWindow命令销毁掉警告框,使主窗体能活动,并且Bring到前端。

如何实现自定义页面的跳转

一开始我们就定义了两个自定义页面:

Page custom WelcomePage
Page custom InstallationPage

从WelcomePage跳转到InstallationPage,这个就是下一步按钮的事件。

创建一个RelGotoPage方法:

Function RelGotoPage
 IntCmp $R9 0 0 Move Move
 StrCmp $R9 "X" 0 Move
 StrCpy $R9 "120"
 Move:
 SendMessage $HWNDPARENT "0x408" "$R9" ""
FunctionEnd

详细解释在这里 http://nsis.sourceforge.net/Go_to_a_NSIS_page

If a number > 0: Goes foward that number of pages. Code of that page will be executed, not returning to this point. If it is bigger than the number of pages that are after that page, it simulates a “Cancel” click.

If a number < 0: Goes back that number of pages. Code of that page will be executed, not returning to this point. If it is bigger than the number of pages that are before that page, it simulates a “Cancel” click.

If X: Simulates a “Cancel” click. Code will go to callback functions, not returning to this point.

If 0: Continues on the same page. Code will still be running after the call.

在下一步的单击事件中加入以下代码,跳转就好了,而且以后的调转RelGotoPage都适用

Function onClickNext
 StrCpy $R9 1
 Call RelGotoPage
 Abort
FunctionEnd

如何用自己的贴图实现CheckBox功能

CheckBox也有系统自带的那种健全的,但是效果没有Button贴皮肤后好,所以弃用之,在第二个页面中创建几个Button跟标签:

${NSD_CreateButton} 26 150 15 15 ""
 Pop $Ck_ShortCut
 StrCpy $1 $Ck_ShortCut
 Call SkinBtn_Checked
 GetFunctionAddress $3 OnClick_CheckShortCut
 SkinBtn::onClick $1 $3
 StrCpy $Bool_ShortCut 1
 ${NSD_CreateLabel} 45 151 100 15 "添加桌面快捷方式"
 Pop $Lbl_ShortCut
 SetCtlColors $Lbl_ShortCut "" transparent ;背景设成透明

创建CheckBox的时候要考虑周全,首先要定义该CheckBox的变量,该CheckBox的皮肤,记录该CheckBox状态的变量$Bool_ShortCut,该CheckBox旁边的提示文字变量$Lbl_ShortCut

Button的贴图跟变换方式在第二节中已经介绍,这里就不啰嗦。

这里的OnClick_CheckShortCut方法不仅仅是一个变换的实现,也通过$Bool_ShortCut记录了当前CheckBox的状态

Function OnClick_CheckShortCut
 ${IF} $Bool_ShortCut == 1
 IntOp $Bool_ShortCut $Bool_ShortCut - 1
 StrCpy $1 $Ck_ShortCut
 Call SkinBtn_UnChecked
 ${ELSE}
 IntOp $Bool_ShortCut $Bool_ShortCut + 1
 StrCpy $1 $Ck_ShortCut
 Call SkinBtn_Checked
 ${EndIf}
FunctionEnd

最后我们在完成安装的时候,可以通过$Bool_ShortCut该变量来了解用户的选择

© 版权声明
THE END
喜欢就支持一下吧
点赞10 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容