我正在编写一个Bootstrapper应用程序,并希望使用WixStandardBootstrapperApplication为它创建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>
第二页(选项页面)根据我的需要工作 - 禁用复选框和安装按钮,只有在选中复选框后才会启用它。但是在第一页(安装页面)上我无法使其正常工作。即使未选中该复选框,也会启用该按钮。我为Checkbox和Button Name尝试了不同的选项,但我无法使其工作。我能做些什么才能让它发挥作用?此外,如果您有任何关于不同选项的文档的链接,请分享。我找到了Thmutil模式的帮助文件,但它没有列出复选框或按钮的各种选项。
欢迎任何建议。随意询问是否有任何不清楚的地方。感谢您的帮助。
答案 0 :(得分:4)
为此,您需要深入研究bootstrapperapplication的代码(WixStdBootstrapperApplication.cpp)。
幸运的是,你的基础是WixStdBootstrapperApplication,我花了很长时间才知道。
您需要做的第一件事就是将EulaAcceptCheckbox放回到页面上,并在其上放置实际的Eula。当您要控制启用/禁用UI元素时,您需要在引导程序应用程序的代码中执行此操作。 BA拥有UI。
现在我们需要更改EulaAcceptCheckbox的行为,以便启用/禁用OptionsButton。
在WndProc中,我们处理用户点击按钮或滚动或执行任何操作时生成的所有消息。在WM_COMMAND下,我们有一个基于LOWORD(wParam)的开关,它是引发消息的控件的ID。
找到“WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX”并看到它调用pBA-&gt; OnClickAcceptCheckbox();
这是方法
void OnClickAcceptCheckbox()
{
BOOL fAcceptedLicense = ThemeIsControlChecked(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX);
ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON, fAcceptedLicense);
}
看起来超级简单吧?在这里你只需要将WIXSTDBA_CONTROL_INSTALL_BUTTON更改为WIXSTDBA_CONTROL_OPTIONS_BUTTON
我们还需要将“选项”按钮设置为默认禁用。为此,我们进入“OnChangeState”并查找if for WIXSTDBA_PAGE_INSTALL
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);
}
}
这里我们删除了提升的东西,因为它出现在安装按钮上,而是启用/禁用选项按钮,具体取决于它是否在主题中定义以及是否选中了accept复选框。
接下来,您需要添加一种方法来找到新的OptionsPage复选框。
你的cpp文件中应该有一个枚举
enum WIXSTDBA_CONTROL
应将其订购到页面上的控件中。在这里,您需要为新的选项复选框控件添加一个新条目,可能是WIXSTDBA_CONTROL_OPTIONS_CHECKBOX
在这个枚举下面你将有一个二维数组
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.
现在我们需要一种方法来处理来自此Control的消息。返回WndProc并在WM_COMMAND下向交换机添加一个新案例,它应该是
case WIXSTDBA_CONTROL_OPTIONS_CHECKBOX:
pBA->OnClickOptionsCheckbox();
return 0;
现在将OnClickOptionsCheckbox方法添加到您的引导程序应用程序中,就像OnClickAcceptCheckbox()
一样void OnClickOptionsCheckbox()
{
BOOL fAccepted = ThemeIsControlChecked(m_pTheme, WIXSTDBA_CONTROL_OPTIONS_CHECKBOX);
ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON, fAccepted);
}
最后,我们需要将从OnChangeState WIXSTDBA_PAGE_INSTALL案例中删除的llElevated内容添加到WIXSTDBA_PAGE_OPTIONS,并设置Install按钮的默认状态
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主题之一的默认行为。