`

Custom dialog for your installer

阅读更多
在这里我总结的是用installshield 打包软件的时候自定义安装界面的问题,阅读下面的文章请确保您具有以下工具的使用经验:
spy++
installshield 12
visual studio 2005
熟悉以下语言:
vc++
installscript
并且熟悉windows的系统操作。

另外本文的例子是基于installscript 类型项目。

各种方法:
1, 利用installshield的Dialogs面板工具。
这里不用复述,它像我们所用过的大多数软件开发工具一样提供了可见即可得的效果,我们可以轻松利用它的拖放操作自定义对话框。

2, 利用外部的资源文件
  •     制作资源文件
              打开你的vs(笔者用的是2005),新建一个MFC DLL项目,在左边找到你的资源面板,添加一个dialog, 添加一些相应的控间,build.
  •     引用资源文件
               把你build出来得资源文件 resouce.dll 添加到installshield 的Support Files language independent 下面
               打开installscript, 新建一个脚本文件,重命名为resouce.h 把你vc 项目里面的resouce.h 文件的内容复制过来, 然后再你的Setup.Rul 文件里面添加引用:
 #include resource.h
添加如下代码:
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->szResoucePath   = SUPPORTDIR ^ "resource.dll";        // Load custom DLL.
    
if ( UseDLL( szResoucePath ) < 0 ) then                          
        abort;
    endif;
显示窗体, 处理消息:
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->nResult = DefineDialog( szDlgName, 
                            hInstance, 
                            szDLL, 
                            IDD_DIALOG_ASKPATH, 
                            
"",
                            hwndParent, 
                            HWND_INSTALL, 
                            DLG_MSG_STANDARD | DLG_CENTERED );
    
if nResult then 
        
// TODO: show error message then exit.
        abort;    
    endif;   
    
    repeat    
// handle dialog message
        nResult 
= WaitOnDialog( szDlgName ); // begin our message loop
        switch ( nResult ) 
            
case DLG_CLOSE: 
                EndDialog (szDlgName);
                ReleaseDialog (szDlgName);
                abort;
            
case DLG_INIT:
                CtrlSetText( szDlgName, IDC_EDIT_PATH, svdir );
                CtrlSetState( szDlgName, IDC_CHECK_OFFICETOOLBAR, BUTTON_CHECKED );
                CtrlSetState( szDlgName, IDC_CHECK_DESTOP, BUTTON_CHECKED );
                CtrlSetState( szDlgName, IDC_CHECK_QUICKLAUNCH, BUTTON_CHECKED ); 
            
case IDC_BUTTON_BROWSE:
                SelectDir ( 
"Choose Folder""", svdir, TRUE );
                CtrlSetText( szDlgName, IDC_EDIT_PATH, svdir );          
            
case RES_PBUT_CANCEL:
                
DoEXIT );
            
case RES_PBUT_NEXT: 
                CtrlGetText( szDlgName, IDC_EDIT_PATH, svdir );  
// get ctrl's value 
                if ( CtrlGetState( szDlgName, IDC_CHECK_OFFICETOOLBAR ) = BUTTON_CHECKED ) then 
                    bAddOfficeToolbar 
=  TRUE;
                
else
                    bAddOfficeToolbar 
= FALSE;
                endif;
                
if ( CtrlGetState( szDlgName, IDC_CHECK_DESTOP ) = BUTTON_CHECKED ) then 
                    bDeskTopShortcut 
= TRUE;
                
else
                    bDeskTopShortcut 
= FALSE;
                endif;
                
if ( CtrlGetState( szDlgName, IDC_CHECK_QUICKLAUNCH ) = BUTTON_CHECKED ) then
                    bQuickLuanchToolbar 
= TRUE;
                
else
                    bQuickLuanchToolbar 
= FALSE;
                endif; 
                bDone 
= TRUE;
            
case RES_PBUT_BACK: 
                EndDialog( szDlgName );
                ReleaseDialog( szDlgName );
                
goto Dlg_SdLicense2;
        endswitch;
    until bDone;    
    EndDialog( szDlgName );   // exit dialog
    ReleaseDialog( szDlgName ); // release resouce

3, 利用函数显示对话框
  •     创建资源文件
打开vs,新建一mfc dll 项目。
添加一个函数, 并注册。
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->extern "C"
LONG WINAPI DisplayAskDestPathDlg( HWND hWndParent,    LPSTR lpszPath,
                                  PBOOL pfAddOfficeToolbar, PBOOL pfDeskTopShortcut, PBOOL pfQuickLuanchToolbar)
{
   
   LONG nReturn;
   TRACE0( 
"Inside ECDialogs.DLL\n" );
   CString    csName 
= _T("");
    
   LPSTR lpszLicense 
= NULL;
   TRY
   {

        CECDialogsDLL dlg(CWnd::FromHandle(hWndParent), 0, pfAddOfficeToolbar, pfDeskTopShortcut, pfQuickLuanchToolbar, lpszPath, lpszLicense, 
                     CECDialogsDLL::askPathDestDialog);

        nReturn = (LONG) dlg.DoModal();
        
if( (nReturn == (LONG)RS_PBUT_RETRY ) ||
            (nReturn 
== (LONG)RS_PBUT_BROWSE) ||
            (nReturn 
== (LONG)RS_PBUT_CANCEL) )
           
return( nReturn );
   }
   
   CATCH_ALL(e)
   {
      
// A failure caused an exception!
      return FALSE;
   }
   END_CATCH_ALL

   
return( nReturn );
}

definition:
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->#ifdef __cplusplus
extern "C" {
#endif
LONG WINAPI DisplayAskDestPathDlg( HWND hWndParent,    LPSTR lpszPath,
                                  PBOOL pfAddOfficeToolbar, PBOOL pfDeskTopShortcut, PBOOL pfQuickLuanchToolbar);

#ifdef __cplusplus
}
#endif

registry:
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->LIBRARY      "ECDialogs"
DESCRIPTION  
'ECDialogs Windows Dynamic Link Library'

EXPORTS
    ; Explicit exports can go here
            
DisplayAskDestPathDlg@1

添加一个dialog并生成一个类:CECDialogsDLL  ,这就是我们要在DisplayAskDestPathDlg这个函数里面调用的窗体了。你可以利用vc的强大功能为他添加各种各样的行为。
  • 应用
同样把这个项目的resouce.h 文件的内容添加到installshield 的resouce.h文件中。
声明函数:
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->prototype ECDIALOGS.DisplayAskDestPathDlg(INTSTRINGINTINTINT);

调用:
再调用的时候,也要先load进dll 文件,具体请参考上面的代码。
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->prototype ECDIALOGS.DisplayAskDestPathDlg(INTSTRINGINTINTINT);

<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->ReleasePackager.exe "C:\My InstallShield 11 Projects\My Project\Media\My Release\Disk Images" "C:\My InstallShield 11 Projects\My Project\Media\My Release\Package\MyPackage.exe" "C:\My Icon Files\MyIcons.dll" 2
4, 利用win api 修改installshield 内部对话框
在有些时候我们会发现,有些对话框我们是不能直接从installshield  Dialogs面板直接修改,也不能用dll和调用外部函数来实现,比如说安装进度对话框(setup status dialog). 我们只能修改它。

  •  修改它的dialog title:
 
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->SetDialogTitle( DLG_STATUS, "mimeo.com - setup" );

这句代码的有效前提是你调用的是 STATUSEX 的setup status dialog.
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->SetStatusWindow( 1"" );
    Enable( STATUSEX );
    StatusUpdate( 
ON100 );
关闭它:
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->Disable( STATUSEX );
  •  修改它的top banner,就是它最上面的图片:
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->DialogSetInfo(DLG_INFO_ALTIMAGE, SUPPORTDIR ^ "topbanner.bmp"TRUE);
          请注意,这句代码会修改你所有的窗体的top banner 的图片, 什么时候调用? 你应该猜到了吧 :-)
           还请注意,这个图片的大小是固定的哦。 那我要显示不一样大小的图片呢? 我要修改,去掉它上面那些该死的文字呢?
          那你就跟我一起来使用windows api 吧。我们的思路是,利用窗体的title 找到当前这个窗口的handle, 利用SetWindowPos api修改窗口的属性。 mfc中所有的控件都是窗体哦。show 代码吧,估计你已经听我罗索的烦了。
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->SetDialogTitle( DLG_STATUS, "mimeo.com - setup" );
    SetStatusWindow( 
1"" );
    Enable( STATUSEX );
    StatusUpdate( 
ON100 );
     
    
// change the setup status dialog's UI  
    try
        hWnd 
= FindWindow( """mimeo.com - setup" );
        
if (hWnd != NULLthen
            HiddenDlgItem( hWnd, 
50 );

            
// change the progress' position
            hWndStatus = GetDlgItem( hWnd, 1500 );
            
if ( hWndStatus != NULL )  then
                SetWindowPos( hWndStatus, 
04926040023, SWP_SHOWWINDOW );  
            endif;
            
//  change the top banner's ctrl weight and height                    
            hWndTopBanner = GetTopBannerCtrlWnd( hWnd );  
            
if ( hWndTopBanner != NULL ) then   
                SetWindowPos( hWndTopBanner, 
000498235, SWP_SHOWWINDOW ); 
            endif;    
            
            
// change botton line's position          
            //hWndStatus = GetDlgItem( hWnd, 1300 );   
            
//if ( hWndStatus != NULL )  then
            
//    SetWindowPos( hWndStatus, 142904902, SWP_SHOWWINDOW );  
            
//endif; 
            
            User32.UpdateWindow( hWnd );    
        endif; 
    catch
    endcatch;    

         
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->function HiddenDlgItem(hWnd, nItemID)      // hidden the ctrl by ctrl's ID
HWND     hWndItem;
begin   
    hWndItem 
= GetDlgItem( hWnd, nItemID );
    
if ( hWndItem != NULL )  then
        SetWindowPos( hWndItem, 
10000, SWP_HIDEWINDOW );  
    endif;
end;         

INT  nArray( 16 );       // save Ctrl's  IDs of setup status dialog
function GetTopBannerCtrlWnd( hWnd)   
INT nIndex, nPicID, nErrorCode;
HWND hWndItem, hWndPic; 
begin
    InitialDlgCtrlIDs( );  
    nIndex 
= 0;
    
while ( nIndex < 16 )      
        nPicID 
=  nArray( nIndex );
        hWndItem 
= GetDlgItem( hWnd, nPicID );  
        
        hWndPic 
= GetWindow( hWndItem, GW_HWNDNEXT );  
        
        
if ( hWndPic != NULL ) then               
            nPicID 
= GetWindowLong( hWndPic, GWL_ID );
            
if ( IsPictureCtrlID( nPicID ) ) then  
                return  hWndPic;
            endif;
        endif; 
        
        hWndItem 
= GetDlgItem( hWnd, nPicID ); 
        hWndPic 
= GetWindow( hWndItem, GW_HWNDPREV );
        
if ( hWndPic != NULL ) then 
            nPicID 
= GetWindowLong( hWndPic, GWL_ID );    
            
if ( IsPictureCtrlID( nPicID ) ) then  
                return  hWndPic;
            endif;
        endif; 
        nIndex 
++;
    endwhile;
    return 
NULL;
end;

function InitialDlgCtrlIDs( )    // 这些是该setup status 窗口中的所有控件ID, 怎么找到的, 用spy++啊。
begin     
    nArray(
0= 0x5dc;
    nArray(
1= 0x34;
    nArray(
2= 0x4b0;
    nArray(
3= 0x2c6;
    nArray(
4= 0x578;
    nArray(
5= 0x32;  
    nArray(
6= 0x33;
    nArray(
7= 0x7;
    nArray(
8= 0x514;
    nArray(
9= 0x2;
    nArray(
10= 0x515;
    nArray(
11= 0x4591;
    nArray(
12= 0x4592;
    nArray(
13= 0x4593;
    nArray(
14= 0x4594;
    nArray(
15= 0x5aa; 
end;   

function IsPictureCtrlID( nItem )   // is top pictrue ctrl's  ID?
INT nIndex; 
begin     
    nIndex 
= 0;
    
while ( nIndex < 16 )   
        
if ( nItem  = nArray( nIndex ) ) then
            return 
FALSE;
        endif;
        nIndex 
++;    
    endwhile;  
    return 
TRUE;
end;

       如果你自己写的代码跑不通,看看这里,你有没有忘了声明系统api乐呢?
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->prototype User32.SetDlgItemText( HWND, INTSTRING ); 
prototype Kernel32.GetLastError(); 
prototype User32.UpdateWindow( HWND );
       注意哦, 系统api 的dll 是不用你自己再load的哦。 如果你又usedll 出现什么问题,别说我没告诉你哦。
  •     修改文字:
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->User32.SetDlgItemText(hWnd, nItemID, szStr);

5, 直接修改installshield生成的资源文件。在我们启动安装程序的时候,会有一个preparing dialog,这个窗体的也是可以修改的。
在 你项目文件夹下搜索这个文件, _setup.dll ,它应该在你的 Media\<release name>\Disk Images\Disk1下面,直接用vs 就可以编辑修改。然后你双击这个文件夹下的setup.exe,你会惊喜的发现你的preparing dialog 已经被修改了。
但是,如果你需要的仅仅是一个单独的可执行文件呢?你再去用installshield rebuild的时候,你会很痛苦的发现_setup.dll 又被installshield改成它原来的了。这里installshield 为我们提供了一个exe ,他可以把media 下面的文件打包成一个self-extracting 的exe。 那就是 ReleasePackager.exe 它在<intall direcotry>\IS12\System 下面。 你可以用命令行执行它一次,如果没有参数,它会打印出帮助。具体参数说明如下:
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->ReleasePackager.exe "disk_images_folder" "package_file" ["icon_file" [icon_index]]

给各例子吧,copy过来的:
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->ReleasePackager.exe "C:\My InstallShield 11 Projects\My Project\Media\My Release\Disk Images" "C:\My InstallShield 11 Projects\My Project\Media\My Release\Package\MyPackage.exe" "C:\My Icon Files\MyIcons.dll" 2

如果你发现它生成了一个C:\My InstallShield 11 Projects\My Project\Media\My Release\Package\MyPackage.exe文件。那你就大功告成了。

遇到的问题:
 
在查找setup status dialog 的最上面的图片控件的时候,笔者发现这个控件的ID 每次运行的时候都市不一样的,而且,每个空间的顺序随着系统的每次系统也是不一样的,所以没有办法用GetWindow来找他的ID, 所以笔者采用了一种比较 stupid的方式来处理。具体请察看函数GetTopBannerCtrlWnd( hWnd)

总结:
installshield 自定义窗体的方式确实很多,也很灵活,但是并不是每种方式都是power,effective, simple的,在不同的场合下我们需要应用不同的方式创建来满足需求。原则就是能用simple 的方式解决的尽量用simple的方式,如果不能,那就只能用其他的方式了。最重要的是能为客户带来一个愉快地安装过程。

相关资源:
Updating the Progress Bar - Macrovision Community
Changing Dialog Box Bitmaps
Macrovision Community - Editing text in STATUSEX dialog
http://helpnet.installshield.com/robo/projects/installshield11helplib/IHelpRelease_ReleasePackagerExe.htm




分享到:
评论

相关推荐

    android custom dialog src

    本资源“android custom dialog src”似乎是一个包含自定义Dialog实现源码的压缩包,适合开发者参考学习或直接应用于项目中。在深入探讨之前,建议先阅读相关博客“UI效果(2): 自定义Dialog”,以便更好地理解和运用...

    custom dialog

    在IT行业中,自定义对话框(Custom Dialog)是一种常见的用户界面元素,用于向用户提供特定的信息或获取特定的输入。在Android开发中,我们经常会遇到需要根据应用需求设计独特外观和功能的对话框的情况,这就是...

    Custom_Dialog_Usage

    `Custom_Dialog_Usage`这个主题正是关注如何在Android应用中创建并使用自定义对话框。通常,系统默认的Dialog样式可能无法满足我们所有的设计需求,这时我们就需要自定义Dialog来达到预期效果。 首先,我们要理解...

    Android Custom Dialog

    在Android开发中,Custom Dialog是一种常见且重要的用户交互方式,它允许开发者自定义对话框的样式、内容和功能,以提供更加个性化和丰富的用户体验。本文将深入探讨如何在Android应用中创建和使用自定义对话框。 ...

    Android Custom Dialog Demo

    在Android开发中,我们经常会需要在android界面上弹出一些对话框,比如询问用户或者让用户选择。,但是只是给出了创建各种类型对话框的方法,并未给出如何获取用户在对话框中做出选择后的数据,即如何监听用户做出的...

    安卓Dialog对话框相关-Custom-Dialog.zip

    本资源“安卓Dialog对话框相关-Custom-Dialog.zip”包含了一些自定义Dialog的示例代码,虽然可能无法全部验证其可用性,但它们提供了很好的学习和参考价值。 首先,我们来了解一下Android中的Dialog。Dialog是...

    Android代码-自定义底部dialog

    This is a custom dialog attached at the bottom Import At the moment the library is in my personal maven repo repositories { maven { url 'http://dl.bintray.com/raphaelbussa/maven' } } dependencies ...

    Dialog System for Unity

    Dialogue System for Unity 可以轻松地为您的游戏添加交互式对话和任务。 它是一个完整,强大的解决方案,包括基于可视节点的编辑器,对话UI,过场动画,任务日志,保存/加载等。 核心是一个精简,高效的会话系统。 ...

    自定义圆角的dialog

    比如,我们可以创建一个`custom_dialog.xml`文件,其中包含一个有圆角的背景、自定义标题、内容区域以及按钮。可以使用`CardView`或者`LinearLayout`配合`shape` drawable来实现圆角效果。 ```xml android:layout...

    flutter-custom-dialog::rocket::rocket::rocket:语义对话框

    :sparkles: flutter_custom_dialog [劳务~~] | 全局对话框函数封装,以语义方式填充对话框内部的内容,提供了当前函数 支持一些语义组件方法以在对话框中填充组件内容 支持自定义语义组件,以便开发人员在对话框中...

    各种自定义Dialog 以及Dialog加载动画

    在Android开发中,自定义Dialog和Dialog加载动画是提升应用用户体验的重要手段。默认的Dialog样式虽然功能齐全,但在追求个性化和美观的今天,往往显得过于简单甚至有些过时。因此,开发者常常需要根据应用的设计...

    dialog动画进入退出的动画

    dialog.setContentView(R.layout.custom_dialog); dialog.getWindow().getAttributes().windowAnimations = R.style.Dialog_Animations; // 其他设置... dialog.show(); ``` 其中,`R.style.Dialog_Animations`是...

    Android应用源码之dialog去除边框代码_dialog.zip

    最后,记得在布局文件(dialog_custom.xml)中设计Dialog的内容。你可以自由地添加所需的视图元素,如TextView、EditText等,并通过Java代码进行交互逻辑的处理。 通过以上步骤,你将成功地为你的Android应用创建了...

    Android自定义显示内容的Dialog

    在这个例子中,`custom_dialog_layout`是XML布局文件,包含了自定义Dialog的UI元素。通过这种方式,我们能够完全控制Dialog的外观和行为。 接下来,我们讨论继承PopupWindow的方法。PopupWindow不是Dialog,但它...

    自定义Dialog样式+大小+位置

    android:background="@color/your_custom_color"&gt; &lt;!-- 在这里添加你的对话框元素,如TextView、EditText等 --&gt; ``` 2. 创建Dialog类:然后,我们可以创建一个自定义的Dialog类,继承自`AlertDialog.Builder`...

    Android Dialog更改样式及显示位置

    dialog.setContentView(R.layout.custom_dialog); ViewGroup.LayoutParams layoutParams = dialog.getWindow().getAttributes(); layoutParams.width = ViewGroup.LayoutParams.WRAP_CONTENT; layoutParams.height =...

    Dialog for PHP-开源

    《Dialog for PHP:开源命令行交互工具》 在IT领域,尤其是在PHP开发中,与用户进行交互是必不可少的。在命令行环境下,这种交互通常较为简单,但有时也需要更复杂的功能,比如输入验证、选择菜单等。这时,"Dialog...

    dialog窗口大集合

    4. **Custom Dialog**:开发者可以根据需求自定义Dialog的布局和行为,提供更加个性化的用户体验。 5. **BottomSheetDialog**:自Android Design Support Library引入,底部滑出的Dialog,适合展示一系列选项或操作...

    Custom-Dlg.rar_C Dlg dial_Change

    1. **C_Dlg_Dial**: 这可能是项目的一个分类或者命名约定,可能指的是“Custom Dialog Dial”或者是“Custom Dialog for Changing”某些属性或功能。 2. **自定义对话框(Custom Dialog)**: 自定义对话框允许...

    各种android弹出dialog效果以及各种dialog样式

    各种android弹出dialog效果以及各种dialog样式各种android弹出dialog效果以及各种dialog样式各种android弹出dialog效果以及各种dialog样式各种android弹出dialog效果以及各种dialog样式各种android弹出dialog效果...

Global site tag (gtag.js) - Google Analytics