InstallShield自定义对话框浅谈(转)
说明:本文档的InstallShield为6.22版本,语言:中文。操作系统为Windows2000。资源编辑工具:Microsoft Visual C ++ 6.0。修改的DLL:_isuer.dll。
此主题相关图片如下:
InstallShield允许添加自定义对话框来满足不同的需求,关于如何创建一个新的对话框资源,有很多参考资料可以查询,就不多说了。这里主要说明的有以下几个方面:
1、 如何创建具有InstallShield Wizard同样风格的对话框。
2、 如何编写脚本来控制自定义对话框上的输入和控件的有效性判断。
一、 创建具有InstallShield Wizard同样风格的对话框在安装向导中可能需要加入一些自定义的步骤,这时可能需要插入一些自定义的对话框来作为某步骤,为了能够把自定义对话框的步骤完全融入导InstallShield Wizard中,即自定义对话框要具有和InstallShield标准步骤同样的风格,下图是InstallShield某标准步骤的图片:
标准步骤示例
在上图中,已经把标准向导对话框的一些风格标注出来了:①、②、③、④,①为该步骤功能说明,并且该说明以黑体字表达;②为对该功能的补充说明;③为InstallShield的图标;④为InstallShield的标注。
那么如何在自定义对话框中实现这些特性呢?下面就对这四个特殊地方作说明:
首先,这四个地方都是一个标签控件,在VC++中表现为静态控件(CStatic)。
①处是表明该步骤功能的地方,那么如何实现黑体的风格呢?其实InstallShield内嵌的机制已经对此作了定义了。在自定义对话框上添加一个静态控件,并且设置该控件的ID为50,并且使ExtendedStyles中的Transparent属性有效,然后在Caption中写上自定义的功能。该控件的位置为(10,3)。设置了这些后,InstallShield会自动把控件中的字体改为黑体。
②处为该同样设置Extended Styles的Transparent属性有效,然后在Caption中写上补充说明。该控件的位置为(17,15)。
③处为InstallShield的图标,该图标也是用静态控件来实现的。在自定义对话框上添加一个静态控件,设置该控件的ID为1200,并且使Styles中的Simple属性有效和Extended Styles的Transparent属性有效,在Caption中填上:@10550,10551;1;0;;0,128,128。该控件的位置为(0,0),大小为(332 x 218)。设置了这些后,InstallShield会自动在该控件中加入该图标。
④处为InstallShield的标注,但是不同于普通效果。在自定义对话框上添加一个静态控件,设置该控件的ID为7,把Caption清空,并且把控件的Visible属性去掉。InstallShield会自动把该控件设置成标准效果。
在设置了以上四个地方之后,还需要在添加一个静态控件,设置该控件的ID为52,把Caption清空,位置为(0,0),大小为(332 x 218)。运行的实际效果,就和标准的安装步骤中的效果一样了。
二、根据输入控制对话框上控件的有效性
在自定义了一个对话框之后,可能需要对对话框上的控件之间的关系进行一些控制,比如当选中了某单选框后,使一些控件有效,而选中其他的单选框后,另一些控件有效等等。要实现这些功能,就需要手动编写InstallShield脚本来实现了。
下面是一个在安装向导中添加了一个自定义对话框,在该步骤中实现在安装的时候在本机器上添加一个SQL Server的数据源。图“自定义对话框效果图”是该自定义对话框的运行效果图:
此主题相关图片如下:
在该自定义对话框中,除了要完成配置SQL Server的数据源之外,还要完成其他一些辅助功能。为了在本机器上配置一个SQL Server数据源,需要输入该数据源的名称、该数据源是针对那个服务器的以及配置的是用户数据源还是系统数据源等数据,而数据库和服务器用户及口令则是完成辅助功能所需要的。只有当输入了必须的数据(如:服务器、数据库、用户名称、数据源等)之后,按钮“下一步”才能有效,为了达到这个要求,就需要对用户的输入进行判断,在InstallShield中可以用WaitOnDialog来得到当前对话框的事件。下面是完成该功能的一个完整脚本代码:
///
// kdcis.rul
//
///
#ifndef __KDCIS_RUL_
#define __KDCIS_RUL_
#include "winsysdll.h"
//
// Pre-defined script dialog constants
//
// ----- Attribute Dialog Controls ------
#define DLG_DSN_SQLSERVER 30001
#defineIDC_RADIO_DSN_USER 1001
#define IDC_RADIO_DSN_SYSTEM 1002
#defineIDC_EDIT_DB_ADDR 1003
#define IDC_EDIT_SQLSERVER_USER_NAME 1004
#define IDC_EDIT_SQLSERVER_USER_PWD 1005
#define IDC_EDIT_SQLSERVER_DSN 1006
#define IDC_EDIT_SQLSERVER_DB 1007
file://----------------------
// Function prototypes
file://----------------------
///
// 显示配置SQLSERVER数据源对话框
// 参数:
// BOOL bFirstStep:是安装的第一步吗?
// BOOL bAllowNotSet:是否允许跳过本次设置
// BYVAL STRING szTitle:对话框的标题
///
prototype BuildSQLServerDSN(BOOL, BOOL, BYVAL STRING);
///
// 校验配置数据源对话框的输入有效性
// 参数:
// HWND hwndDlg:配置对话框的句柄,从CmdGetHwndDlg中得到
// BOOL bAllowNotSet:是否允许跳过本次设置
// 备注:
// CheckSQLServerDSNInputValid:对SQLSERVER数据源配置进行校验
//
prototype CheckSQLServerDSNInputValid(HWND, BOOL);
file://----------------------
// Variable declaration
file://----------------------
file://----------------------
// Macro declaration
file://----------------------
#define DSN_SQLSERVER_DLG "ConfigSQLServerDSNDLG"
/*------------------------------------------------------------------------*/
/* */
/* Function: BuildSQLServerDSN */
/* */
/* Descrip: use custom sqlserver's dsn dlg to createdsn. */
/* */
/* Misc: */
/* */
/*------------------------------------------------------------------------*/
function BuildSQLServerDSN(bFirstStep, bAllowNotSet,szTitle)
BOOL bDone;
NUMBER nMessage;
STRING szSQLAddr,szSQLDB, szDBUserName, szDBUserPwd, szSQLDSN;
SHORT nDSNType;
STRING svArg[1024];
STRING svDSN,svAddr, svDB, svUID, svPWD;
NUMBER nSplitPos;
HWND hwndDlg;
BOOL bBuildResult;
SHORT wErrMsgLen;
STRINGszErrMsg[MAX_PATH + 1];
LONG dwErrCode;
begin
bDone = FALSE;
// 用EzDefineDialog定义一个对话框
nMessage =EzDefineDialog(DSN_SQLSERVER_DLG, ISUSER, "", DLG_DSN_SQLSERVER);
if(nMessage = DLG_ERR) then
MessageBox("不能进行配置SQLSERVER数据源——找不到对话框", SEVERE);
bDone = TRUE;
endif;
while(bDone = FALSE)
nMessage =WaitOnDialog(DSN_SQLSERVER_DLG);
switch(nMessage)
case DLG_INIT:
hwndDlg= CmdGetHwndDlg(DSN_SQLSERVER_DLG);
CheckSQLServerDSNInputValid(hwndDlg, bAllowNotSet);
if(bFirstStep) then
_WinSubEnableControl(hwndDlg, SD_PBUT_BACK, 0);
endif;
_WinSubSetWindowTitle(hwndDlg, szTitle);
CtrlSetState(DSN_SQLSERVER_DLG, IDC_RADIO_DSN_USER, BUTTON_CHECKED);
case DLG_ERR:
MessageBox("不能显示配置SQLSERVER数据源对话框", SEVERE);
bDone = TRUE;
case CANCEL:
bDone = TRUE;
case DLG_CLOSE:
bDone = TRUE;
caseSD_PBUT_CONTINUE:
// 调用接口添加一个dsn
// ...
CtrlGetText(DSN_SQLSERVER_DLG, IDC_EDIT_DB_ADDR, szSQLAddr);
CtrlGetText(DSN_SQLSERVER_DLG, IDC_EDIT_SQLSERVER_DB, szSQLDB);
CtrlGetText(DSN_SQLSERVER_DLG, IDC_EDIT_SQLSERVER_USER_NAME, szDBUserName);
CtrlGetText(DSN_SQLSERVER_DLG, IDC_EDIT_SQLSERVER_USER_PWD, szDBUserPwd);
CtrlGetText(DSN_SQLSERVER_DLG, IDC_EDIT_SQLSERVER_DSN, szSQLDSN);
if(StrLength(szSQLAddr) = 0) then
if(AskYesNo("没有输入服务器,是否以后进行配置?", YES) = NO) then
_WinSubFocusControl(hwndDlg, IDC_EDIT_DB_ADDR);
else
bDone = TRUE;
endif;
elseif(StrLength(szSQLDB) = 0) then
if(AskYesNo("没有输入数据库,是否以后进行配置?", YES) = NO) then
_WinSubFocusControl(hwndDlg, IDC_EDIT_SQLSERVER_DB);
else
bDone = TRUE;
endif;
elseif(StrLength(szDBUserName) = 0) then
if(AskYesNo("没有输入数据库用户,是否以后进行配置?", YES) = NO) then
_WinSubFocusControl(hwndDlg, IDC_EDIT_SQLSERVER_USER_NAME);
else
bDone = TRUE;
endif;
elseif(StrLength(szSQLDSN) = 0) then
if(AskYesNo("没有输入数据源名称,是否以后进行配置?", YES) = NO) then
_WinSubFocusControl(hwndDlg, IDC_EDIT_SQLSERVER_DSN);
else
bDone = TRUE;
endif;
else
// 已经获取了所有数据,可以调用SQLConfigDataSource添加数据源了
// 组织语句
// 注:由于DSN不保存UID和PWD,所以在Attribute中不能加入这两个
// 关键字,并且每个关键子之间用'\0'分割,由于InstallShield
// 中不支持一个字符串中间存在'\0',因此,不能直接用+连接这些
// 关键字,下面是一个变通的方法
if(CtrlGetState(DSN_SQLSERVER_DLG, IDC_RADIO_DSN_USER) = BUTTON_CHECKED) then
nDSNType = ODBC_ADD_DSN;
else
nDSNType = ODBC_ADD_SYS_DSN;
endif;
svDSN = "DSN=" + szSQLDSN;
svAddr = "SERVER=" + szSQLAddr;
svDB = "DATABASE=" + szSQLDB;
svUID = "UID=" + szDBUserName;
svPWD = "PWD=" + szDBUserPwd;
svArg = svDSN + ' ' + svAddr + ' ' + svDB;
nSplitPos = StrLength(svDSN);
svArg[nSplitPos] = '\0';
nSplitPos += StrLength(svAddr) + 1;
svArg[nSplitPos] = '\0';
nSplitPos += StrLength(svDB) + 1;
svArg[nSplitPos] = '\0';
// 调用ODBCCP32中的SQLConfigDataSource添加一个DSN
// 如果返回FALSE,表示添加失败,这时可以调用
// SQLInstallerError来得到失败的原因
bBuildResult = SQLConfigDataSource(NULL, nDSNType, "SQL Server",svArg);
if(bBuildResult) then
// 如果添加成功
bDone = TRUE;
else
// 添加失败
wErrMsgLen = MAX_PATH;
SQLInstallerError(1, &dwErrCode, szErrMsg, wErrMsgLen, &wErrMsgLen);
if(bAllowNotSet) then
szErrMsg= "配置数据源失败——" + szErrMsg + "!是否以后进行配置?";
if(AskYesNo(szErrMsg, YES) = NO) then
bDone = FALSE;
else
bDone = TRUE;
endif;
else
szErrMsg = "配置数据源失败——" + szErrMsg + "!";
MessageBox(szErrMsg, SEVERE);
endif;
endif;
endif;
case SD_PBUT_BACK:
// 上一步
bDone = TRUE;
caseSD_PBUT_EXITSETUP:
bDone = TRUE;
caseIDC_RADIO_DSN_USER:
CheckSQLServerDSNInputValid(hwndDlg, bAllowNotSet);
caseIDC_RADIO_DSN_SYSTEM:
CheckSQLServerDSNInputValid(hwndDlg, bAllowNotSet);
caseIDC_EDIT_DB_ADDR:
CheckSQLServerDSNInputValid(hwndDlg, bAllowNotSet);
caseIDC_EDIT_SQLSERVER_USER_NAME:
CheckSQLServerDSNInputValid(hwndDlg, bAllowNotSet);
caseIDC_EDIT_SQLSERVER_USER_PWD:
CheckSQLServerDSNInputValid(hwndDlg, bAllowNotSet);
caseIDC_EDIT_SQLSERVER_DSN:
CheckSQLServerDSNInputValid(hwndDlg, bAllowNotSet);
caseIDC_EDIT_SQLSERVER_DB:
CheckSQLServerDSNInputValid(hwndDlg, bAllowNotSet);
endswitch;
endwhile;
EndDialog(DSN_SQLSERVER_DLG);
ReleaseDialog(DSN_SQLSERVER_DLG);
if(nMessage = SD_PBUT_CONTINUE) then
return NEXT;
elseif(nMessage = SD_PBUT_BACK) then
return BACK;
else
Do(EXIT);
endif;
end;
/*------------------------------------------------------------------------*/
/* */
/* Function: CheckSQLServerDSNInputValid */
/* */
/* Descrip: check the input data isvalid. */
/* do not need to check the pwd ifempty */
/* Misc: */
/* */
/*------------------------------------------------------------------------*/
function CheckSQLServerDSNInputValid(hwndDlg, bAllowNotSet)
STRING szDBUserName;
STRING szSQLDB;
STRING szSQLAddr;
STRING szSQLDSN;
begin
if(bAllowNotSet) then
_WinSubEnableControl(hwndDlg, SD_PBUT_CONTINUE, 1);
return 1;
endif;
if((CtrlGetState(DSN_SQLSERVER_DLG,IDC_RADIO_DSN_USER) = BUTTON_UNCHECKED) &&
(CtrlGetState(DSN_SQLSERVER_DLG,IDC_RADIO_DSN_SYSTEM) = BUTTON_UNCHECKED)) then
_WinSubEnableControl(hwndDlg,SD_PBUT_CONTINUE, 0);
return0;
endif;
CtrlGetText(DSN_SQLSERVER_DLG,IDC_EDIT_SQLSERVER_USER_NAME, szDBUserName);
if(StrLength(szDBUserName) = 0) then
_WinSubEnableControl(hwndDlg, SD_PBUT_CONTINUE, 0);
return 0;
endif;
CtrlGetText(DSN_SQLSERVER_DLG,IDC_EDIT_SQLSERVER_DSN, szSQLDSN);
if(StrLength(szSQLDSN) = 0) then
_WinSubEnableControl(hwndDlg, SD_PBUT_CONTINUE, 0);
return 0;
else
if(!SQLValidDSN(szSQLDSN)) then
MessageBox("输入了无效的数据源名称!", INFORMATION);
_WinSubFocusControl(hwndDlg, IDC_EDIT_SQLSERVER_DSN);
return 0;
endif;
endif;
CtrlGetText(DSN_SQLSERVER_DLG,IDC_EDIT_SQLSERVER_DB, szSQLDB);
if(StrLength(szSQLDB) = 0) then
_WinSubEnableControl(hwndDlg, SD_PBUT_CONTINUE, 0);
return 0;
endif;
CtrlGetText(DSN_SQLSERVER_DLG,IDC_EDIT_DB_ADDR, szSQLAddr);
if(StrLength(szSQLAddr) = 0) then
_WinSubEnableControl(hwndDlg, SD_PBUT_CONTINUE, 0);
return 0;
endif;
_WinSubEnableControl(hwndDlg,SD_PBUT_CONTINUE, 1);
return 1;
end;
#endif // __KDCIS_RUL
//===========================================================================
// 文件:winsysdll.h
// 描述:定义系统动态库的函数原型
//
// 更新:
// 2004/02/06
//===========================================================================
#ifndef __WINSYSDLL_H__
#define __WINSYSDLL_H__
//----------------------------------------------------
//Prototype user32 DLL functions used in project.
//----------------------------------------------------
//----------------------------------------------------
//Prototype ocbccp32 DLL functions used in project.
//----------------------------------------------------
#ifndef ODBC_ADD_DSN
#defineODBC_ADD_DSN 1
#endif
#ifndef ODBC_CONFIG_DSN
#defineODBC_CONFIG_DSN 2
#endif
#ifndef ODBC_ADD_SYS_DSN
#defineODBC_ADD_SYS_DSN 4
#endif
#ifndef ODBC_CONFIG_SYS_DSN
#defineODBC_CONFIG_SYS_DSN 5
#endif
#ifndef ODBC_INSTALL_COMPLETE
#define ODBC_INSTALL_COMPLETE 2
#endif
#ifndef ODBC_INSTALL_DEIVER
#defineODBC_INSTALL_DEIVER 1
#endif
#ifndef SQL_MAX_MESAGE_LENGTH
#define SQL_MAX_MESSAGE_LENGTH 512
#endif
#ifndef SQL_SUCCESS_WITH_INFO
#define SQL_SUCCESS_WITH_INFO 1
#endif
#ifndef SQL_NO_DATA
#defineSQL_NO_DATA 100
#endif
#ifndef SQL_ERROR
#defineSQL_ERROR -1
#endif
prototype BOOLODBCCP32.SQLConfigDataSource(HWND, SHORT, BYVAL STRING, BYVAL STRING);
prototype BOOL ODBCCP32.SQLValidDSN(BYVALSTRING);
prototype BOOLODBCCP32.SQLInstallerError(SHORT, POINTER, BYREF STRING, SHORT, POINTER);
#endif // __WINSYSDLL_H__
以上是本人对在InstallShield下自定义对话框的一些心得。在建立自定义对话框的时候,还是有一些疑惑,当在自定义对话框上添加了IP地址控件之后,WaitOnDialog始终返回DLG_ERR的错误,不知道如何在自定义对话框上添加IP地址控件,至于其他的控件,则没有尝试过。
转自:http://wenku.baidu.com/link?url=3Ou7r_Wkp6cWEGvDRIzUkJ9Y9V0g0kL-Stku4ToLAkaJbuQmXKjrZLyTLt-gpBJtT76R-MqEFyYQE4tkn-G1VAggPyXzm76Omd_PGzWPuTm
InstallShield自定义对话框浅谈(转)相关推荐
- build 之前执行task_浅谈VS编译自定义编译任务—MSBuild Task(csproject)-阿里云开发者社区...
在上一篇浅谈.NET编译时注入(C#-->IL)中我们简单的反编译查看了几种c#语法糖和PostSharp在编译成IL时为我做的MSIL注入.紧接着在这节,要来看的就是MSBuild Task. ...
- iOS 自定义转场动画浅谈
代码地址如下: http://www.demodashi.com/demo/11612.html 路漫漫其修远兮,吾将上下而求索 前记 想研究自定义转场动画很久了,时间就像海绵,挤一挤还是有的,花了差 ...
- 浅谈eform自定义表单工具和协同办公系统
浅谈eform自定义表单工具和协同办公系统 提起"协同办公",随便在百度或者Google搜索一下,就能让你看到眼花缭乱的信息,国内的各大协同办公软件厂商都在鼓吹着自己对协同的理解和 ...
- css中字体下划线样式,css下划线 浅谈css自定义下划线
使用css样式对一段文字或一段文字中其中几个文字设置虚线效果的下划线如何实现?我们知道css字体下划线使用text-decoration样式实现,而虚线下划线则不能使用此css样式属性.要实现通过下边 ...
- 浅谈android中的自定义封装易用的Dialog
转载地址:http://blog.csdn.net/u013064109/article/details/51990526 好久没写Android的博客,最近在做一个android的项目,里面用到我们 ...
- 【转】浅谈.net remoting 与webservice
1. .NET Remoting .NET Remoting是微软随.NET推出的一种分布式应用解决方案,被誉为管理应用程序域之间的 RPC 的首选技,它允许不同应用程序域之间进行通信(这里的通信可以 ...
- 浅谈Hybrid技术的设计与实现【转】
https://www.cnblogs.com/yexiaochai/p/4921635.html 前言 浅谈Hybrid技术的设计与实现 浅谈Hybrid技术的设计与实现第二弹 浅谈Hybrid技术 ...
- 浅谈Hybrid技术的设计与实现第二弹
前言 浅谈Hybrid技术的设计与实现 浅谈Hybrid技术的设计与实现第二弹 浅谈Hybrid技术的设计与实现第三弹--落地篇 接上文:浅谈Hybrid技术的设计与实现(阅读本文前,建议阅读这个先) ...
- 浅谈百度地图的简单开发之实现地图全景,内景展示功能(四)
今天,我就接着来浅谈一下关于百度地图的内景,外景的展示功能.今天具体要实现的功能就是输入该地点的名称然后就展示该地点的内景图片,有内景就展示内景,没有则显示该地点的街景,该功能是参考百度地图官方的AP ...
最新文章
- 通过蜜罐技术获取攻击者手机号、微信号【网络安全】
- Django实现的博客系统中使用富文本编辑器ckeditor
- 【Android开发—智能家居系列】(一):智能家居原理
- 【剑指offer】_16 构建乘积数组
- 中国工程院出台“八不准” 为院士增选“划红线”
- 所以進入到二十一世紀之後
- java图形用户界面设计实验_java图形用户界面设计实验报告(共10篇).doc
- 在QQ浏览器打开html,QQ浏览器显示网页打开错误的解决方法
- Excel表格-数据统计
- CSS3权威指南读书笔记
- 为什么要创业,有人盆满钵满、有人别无选择,区别在创业思维
- 家庭影院.液晶电视.液晶电视连接电脑全功略
- 中科大计算机网络空间安全,2020年中国科学技术大学网络空间安全考研经验分享...
- android制作3d打印机,基于Rayland主板的3D打印机指令控制Android(部分)实现
- 1PPS:秒脉冲 相关概念理解
- buildroot使用详解
- Matlab 归一化函数premnmx [-1,1]
- vue + css3实现微信录制播放语音效果
- 【Python 初学者】从零开始构建自己的神经网络
- 微信公众号开发之关注推送图文消息
热门文章
- 医疗手术机器人 双目视觉导航方式产品汇总
- java输入多个数据_Java中怎么读入一行输入空格隔开的多个数据
- 一个行程问题与对应的数列求和
- 什么是Galil(加利尔)运动控制卡,它是用来干嘛的呢?galil开发文件dmc32.dll,动态链接库,API
- idea编译报错:Refer to the generated Javadoc files in ‘..\target\apidocs‘ dir. 解决
- 基于C++的《元素战争》基于win32框架的电脑游戏设计
- 佳明手表APP开发系列01——简单汉化英文版
- mac php开发套件_Mac 下搭建 PHP 开发环境的步骤
- 什么是MyBatis
- NTP 时区+时间同步