User interface 引导程序应用程序UI-如何在页面之间移动

User interface 引导程序应用程序UI-如何在页面之间移动,user-interface,wix,bootstrapper,burn,wixstdba,User Interface,Wix,Bootstrapper,Burn,Wixstdba,我正在编写一个Bootstrapper应用程序,并希望使用wixstandardbootstrapper应用程序为其创建UI。我希望UI在第一个页面安装页面上,我看到标准EULA和一个复选框,该复选框显示我接受,以及一个按钮,以便在下一个页面选项页面上继续操作,只有在我选中该复选框后,该选项页面才应启用。在下一页,我列出了一些文本,并希望有另一个复选框,这类再次表示我接受和一个按钮来安装,只有在我选中复选框后才能启用 <Page Name="Install"> <Text

我正在编写一个Bootstrapper应用程序,并希望使用wixstandardbootstrapper应用程序为其创建UI。我希望UI在第一个页面安装页面上,我看到标准EULA和一个复选框,该复选框显示我接受,以及一个按钮,以便在下一个页面选项页面上继续操作,只有在我选中该复选框后,该选项页面才应启用。在下一页,我列出了一些文本,并希望有另一个复选框,这类再次表示我接受和一个按钮来安装,只有在我选中复选框后才能启用

<Page Name="Install">
  <Text X="154" Y="12" Width="-65" Height="21" DisablePrefix="yes">#(loc.Title)</Text>
  <Image X="120" Y="20" Width="54" Height="325" ImageFile="logo.png"/>
  <Richedit Name="EulaRichedit" X="154" Y="60" Width="-21" Height="-76" TabStop="yes" FontId="0" HexStyle="0x800000" />
  <Checkbox Name="OptionsCheckbox" X="-11" Y="-41" Width="246" Height="17" TabStop="yes" FontId="3" HideWhenDisabled="yes">I accept.</Checkbox>
  <Button Name="WelcomeCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.InstallCloseButton)</Button>
  <Button Name="OptionsButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" Text="Proceed" HideWhenDisabled="yes">Next</Button>
</Page>
<Page Name="Options">
  <Text X="185" Y="11" Width="-11" Height="32" FontId="1">#(loc.OptionsHeader)</Text>
  <Image X="0" Y="0" Width="177" Height="325" ImageFile="logoside.png"/>
  <Text X="180" Y="61" Width="-11" Height="17" FontId="3">Some text.</Text>
  <Checkbox Name="EulaAcceptCheckbox" X="180" Y="251" Width="246" Height="17" TabStop="yes" FontId="3" HideWhenDisabled="yes">#(loc.OptionsButton)</Checkbox>
  <Button Name="InstallButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" Text="Proceed">#(loc.InstallInstallButton)</Button>
  <Button Name="OptionsCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.InstallCloseButton)</Button>
</Page>
第二个页面选项页面是根据我的需要工作的-复选框和安装按钮被禁用,并且只有在选中复选框后才被启用。但是在第一页安装页面上,我无法使它工作。即使未选中复选框,该按钮也将启用。我尝试了复选框和按钮名称的不同选项,但无法使其工作。我能做些什么使它工作?此外,如果您有任何不同选项文档的链接,请与他人分享。我找到了带有Thmutil模式的帮助文件,但它没有列出复选框或按钮的各种选项


欢迎任何建议。如果有什么不清楚的地方,请随时询问。提前感谢您的帮助。

要做到这一点,您需要深入研究bootstrapperapplication WixStdBootstrapperApplication.cpp的代码

幸运的是,这是基于wixstdbootstrapper应用程序的,我花了很多时间了解它

您需要做的第一件事是将EulaAcceptCheckbox放回到页面上,并在其上显示实际的Eula。当您要控制启用/禁用的UI元素时,需要从引导程序应用程序的代码中执行此操作。广管局拥有用户界面

现在我们需要更改EulaAcceptCheckbox的行为,以便启用/禁用选项按钮

在WndProc中,我们处理用户单击按钮、滚动或执行任何操作时生成的所有消息。在WM_命令下,我们有一个基于LOWORDwParam的开关,LOWORDwParam是引发消息的控件的ID

找到WIXSTDBA_CONTROL_EULA_ACCEPT_复选框,并查看它调用pBA->OnClickAcceptCheckbox

这里是方法

void OnClickAcceptCheckbox()
{
    BOOL fAcceptedLicense = ThemeIsControlChecked(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX);
    ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON, fAcceptedLicense);
}
看起来超级简单对吧?这里您只需将WIXSTDBA_CONTROL_INSTALL_按钮更改为WIXSTDBA_CONTROL_OPTIONS_按钮

我们还需要将选项按钮设置为默认禁用。为此,我们进入OnChangeState并查找if for WIXSTDBA_页面_安装

if (m_rgdwPageIds[WIXSTDBA_PAGE_INSTALL] == dwNewPageId) // on the "Install" page, ensure the install button is enabled/disabled correctly.
{
    LONGLONG llElevated = 0;
    if (m_Bundle.fPerMachine)
    {
        BalGetNumericVariable(WIXBUNDLE_VARIABLE_ELEVATED, &llElevated);
    }
    ThemeControlElevates(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON, (m_Bundle.fPerMachine && !llElevated));

    // If the EULA control exists, show it only if a license URL is provided as well.
    if (ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_EULA_LINK))
    {
        BOOL fEulaLink = (m_sczLicenseUrl && *m_sczLicenseUrl);
        ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_EULA_LINK, fEulaLink);
        ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX, fEulaLink);
    }

    BOOL fAcceptedLicense = !ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX) || !ThemeControlEnabled(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX) || ThemeIsControlChecked(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX);
    ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON, fAcceptedLicense);

    // If there is an "Options" page, the "Options" button exists, and it hasn't been suppressed, then enable the button.
    BOOL fOptionsEnabled = m_rgdwPageIds[WIXSTDBA_PAGE_OPTIONS] && ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_OPTIONS_BUTTON) && !m_fSuppressOptionsUI;
    ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_OPTIONS_BUTTON, fOptionsEnabled);

    // Show/Hide the version label if it exists.
    if (m_rgdwPageIds[WIXSTDBA_PAGE_OPTIONS] && ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_VERSION_LABEL) && !m_fShowVersion)
    {
        ThemeShowControl(m_pTheme, WIXSTDBA_CONTROL_VERSION_LABEL, SW_HIDE);
    }
}
我们需要将此块更新为

if (m_rgdwPageIds[WIXSTDBA_PAGE_INSTALL] == dwNewPageId) // on the "Install" page, ensure the install button is enabled/disabled correctly.
{                    
    // If the EULA control exists, show it only if a license URL is provided as well.
    if (ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_EULA_LINK))
    {
        BOOL fEulaLink = (m_sczLicenseUrl && *m_sczLicenseUrl);
        ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_EULA_LINK, fEulaLink);
        ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX, fEulaLink);
    }

    BOOL fAcceptedLicense = !ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX) || !ThemeControlEnabled(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX) || ThemeIsControlChecked(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX);

    // If there is an "Options" page, the "Options" button exists, and it hasn't been suppressed, then enable the button.
    BOOL fOptionsEnabled = m_rgdwPageIds[WIXSTDBA_PAGE_OPTIONS] && ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_OPTIONS_BUTTON) && !m_fSuppressOptionsUI;
    ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_OPTIONS_BUTTON, fOptionsEnabled & fAcceptedLicense);

    // Show/Hide the version label if it exists.
    if (m_rgdwPageIds[WIXSTDBA_PAGE_OPTIONS] && ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_VERSION_LABEL) && !m_fShowVersion)
    {
        ThemeShowControl(m_pTheme, WIXSTDBA_CONTROL_VERSION_LABEL, SW_HIDE);
    }
}
在这里,我们删除了提升的内容,因为它位于安装按钮上,而是根据主题中是否定义了选项按钮以及是否选中了接受复选框来启用/禁用选项按钮

接下来,您需要添加一种方法来定位新选项页面复选框

<Page Name="Install">
  <Text X="154" Y="12" Width="-65" Height="21" DisablePrefix="yes">#(loc.Title)</Text>
  <Image X="120" Y="20" Width="54" Height="325" ImageFile="logo.png"/>
  <Richedit Name="EulaRichedit" X="154" Y="60" Width="-21" Height="-76" TabStop="yes" FontId="0" HexStyle="0x800000" />
  <Checkbox Name="OptionsCheckbox" X="-11" Y="-41" Width="246" Height="17" TabStop="yes" FontId="3" HideWhenDisabled="yes">I accept.</Checkbox>
  <Button Name="WelcomeCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.InstallCloseButton)</Button>
  <Button Name="OptionsButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" Text="Proceed" HideWhenDisabled="yes">Next</Button>
</Page>
<Page Name="Options">
  <Text X="185" Y="11" Width="-11" Height="32" FontId="1">#(loc.OptionsHeader)</Text>
  <Image X="0" Y="0" Width="177" Height="325" ImageFile="logoside.png"/>
  <Text X="180" Y="61" Width="-11" Height="17" FontId="3">Some text.</Text>
  <Checkbox Name="EulaAcceptCheckbox" X="180" Y="251" Width="246" Height="17" TabStop="yes" FontId="3" HideWhenDisabled="yes">#(loc.OptionsButton)</Checkbox>
  <Button Name="InstallButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" Text="Proceed">#(loc.InstallInstallButton)</Button>
  <Button Name="OptionsCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.InstallCloseButton)</Button>
</Page>
您的cpp文件中应该有一个枚举

enum WIXSTDBA_CONTROL
应将其排序到页面上的控件中。在这里,您需要为新选项复选框控件添加一个新条目,可能是WIXSTDBA_control_Options_复选框

在此枚举下,您将有一个二维数组

static THEME_ASSIGN_CONTROL_ID vrgInitControls[] = 
您需要在此处添加一个新条目,该条目与插入枚举的位置相同。插入的数组项应如下所示

{ WIXSTDBA_CONTROL_OPTIONS_CEHCKBOX, L"OptionsCheckbox" },  //The string should match the Name of the checkbox in the theme xml.
现在我们需要一种方法来处理来自此控件的消息。返回WndProc,并在WM_命令下为开关添加一个新的案例

case WIXSTDBA_CONTROL_OPTIONS_CHECKBOX:
    pBA->OnClickOptionsCheckbox();
    return 0;
现在将onClickOptions复选框方法添加到引导程序应用程序中,就像OnClickAcceptCheckbox一样

void OnClickOptionsCheckbox()
{
    BOOL fAccepted = ThemeIsControlChecked(m_pTheme, WIXSTDBA_CONTROL_OPTIONS_CHECKBOX);
    ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON, fAccepted);
}
最后,我们需要将从OnChangeState WIXSTDBA_PAGE_安装案例中删除的L相关内容添加到WIXSTDBA_PAGE_选项中,并设置安装按钮的默认状态

else if (m_rgdwPageIds[WIXSTDBA_PAGE_OPTIONS] == dwNewPageId)
{
    HRESULT hr = BalGetStringVariable(WIXSTDBA_VARIABLE_INSTALL_FOLDER, &sczUnformattedText);
    if (SUCCEEDED(hr))
    {
        // If the wix developer is showing a hidden variable in the UI, then obviously they don't care about keeping it safe
        // so don't go down the rabbit hole of making sure that this is securely freed.
        BalFormatString(sczUnformattedText, &sczText);
        ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_FOLDER_EDITBOX, sczText);
    }
}
将更改为

else if (m_rgdwPageIds[WIXSTDBA_PAGE_OPTIONS] == dwNewPageId)
{
    LONGLONG llElevated = 0;
    if (m_Bundle.fPerMachine)
    {
        BalGetNumericVariable(WIXBUNDLE_VARIABLE_ELEVATED, &llElevated);
    }
    ThemeControlElevates(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON, (m_Bundle.fPerMachine && !llElevated));       

    BOOL fAccepted = !ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_OPTIONS_CHECKBOX) || !ThemeControlEnabled(m_pTheme, WIXSTDBA_CONTROL_OPTIONS_CHECKBOX) || ThemeIsControlChecked(m_pTheme, WIXSTDBA_CONTROL_OPTIONS_CHECKBOX);
    ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON, fAccepted);

    HRESULT hr = BalGetStringVariable(WIXSTDBA_VARIABLE_INSTALL_FOLDER, &sczUnformattedText);
    if (SUCCEEDED(hr))
    {
        // If the wix developer is showing a hidden variable in the UI, then obviously they don't care about keeping it safe
        // so don't go down the rabbit hole of making sure that this is securely freed.
        BalFormatString(sczUnformattedText, &sczText);
        ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_FOLDER_EDITBOX, sczText);
    }
}
在这个实现中,我仍然会改变一些事情,但我强烈建议尝试了解bootstrapper应用程序的功能和工作方式

如果要在安装过程中更改UI的行为,需要熟悉此处的代码。您可以添加新页面、添加控件、设置变量以及其他内容


如果这看起来像是大量的工作来解决这些问题,我肯定会考虑你是否真的需要这种行为来应对默认的WixSTDBA主题之一的默认行为。< /P>哦,这是一个有趣的事情。要想让这一切顺利进行,实际上还有很多事情要做。今天晚些时候,我会在午餐休息时写下一个好的答案,非常感谢你的详细回答。我将尝试它,并更新它对我的影响。但是有一个问题,我假设在修改这个之后,我将不得不为它生成一个dll。我如何将其插入到使用VS2012的项目中。为这个DLL添加对VS的引用,我必须在wxs文件中做任何修改吗?此外,这是否会与将出现在f中的现有dll冲突
或者WixStdBootstrapperApplication?您将需要生成一个新的dll,您可以替换wix dll,也可以引用修改后的dll源文件构建自己的dll。查看这两个文件,了解如何定义自己的BA。我试图通过更改您提到的文件来创建dll,但在打开wixstdba.vcxproj文件时出错。我为此写了一篇新文章--你能看一下吗。