- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在编写一个 Bootstrapper 应用程序,并希望使用 WixStandardBootstrapperApplication 为其创建 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 架构的帮助文件,但它没有列出复选框或按钮的各种选项。
欢迎提出任何建议。如果有任何不清楚的地方,请随时询问。提前感谢您的帮助。
最佳答案
为此,您需要深入研究 Bootstrap 应用程序 (WixStdBootstrapperApplication.cpp) 的代码。
幸运的是,您是基于我花了很长时间才了解的 WixStdBootstrapperApplication。
您需要做的第一件事是将 EulaAcceptCheckbox 放回带有实际 Eula 的页面上。当您要控制启用/禁用的 UI 元素时,您需要从 Bootstrap 应用程序的代码中执行此操作。 BA 拥有 UI。
现在我们需要更改 EulaAcceptCheckbox 的行为,以便它启用/禁用 OptionsButton。
在 WndProc 中,我们处理用户单击按钮、滚动或执行任何操作时生成的所有消息。在 WM_COMMAND 下,我们有一个基于 LOWORD(wParam) 的开关,它是引发消息的控件的 ID。
找到“WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX”并看到它调用了 pBA->OnClickAcceptCheckbox();
这是方法
void OnClickAcceptCheckbox()
{
BOOL fAcceptedLicense = ThemeIsControlChecked(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX);
ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON, fAcceptedLicense);
}
看起来 super 简单吧?在这里,您只需将 WIXSTDBA_CONTROL_INSTALL_BUTTON 更改为 WIXSTDBA_CONTROL_OPTIONS_BUTTON
我们还需要将选项按钮设置为默认禁用。为此,我们进入“OnChangeState”并寻找 WIXSTDBA_PAGE_INSTALL 的 if
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);
}
}
我们需要将这个 block 更新为
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);
}
}
这里我们删除了提升的东西,因为它会出现在安装按钮上,而是根据它是否在主题中定义以及是否选中接受复选框来启用/禁用选项按钮。
接下来,您需要添加一种方法来定位新的 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.
现在我们需要一种方法来处理来自该控件的消息。回到 WndProc 并在 WM_COMMAND 下的开关中添加一个新案例,它应该是
case WIXSTDBA_CONTROL_OPTIONS_CHECKBOX:
pBA->OnClickOptionsCheckbox();
return 0;
现在将 OnClickOptionsCheckbox 方法添加到您的 Bootstrap 应用程序,就像 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 并设置安装按钮的默认状态
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);
}
}
对于此实现,我仍会更改一些内容,但我强烈建议您尝试了解 Bootstrap 应用程序的功能及其工作原理。
如果您想在安装过程中更改 UI 的行为,您需要熟悉此处的代码。您可以添加新页面、添加控件并设置变量以及其他一些内容。
如果这看起来工作量很大(我自己肯定会弄清楚这一切)请考虑您是否真的需要这种类型的行为而不是默认的 wixstdba 主题之一的默认行为。
关于user-interface - Bootstrapper 应用程序 UI - 如何在页面之间移动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36879242/
我是 C 语言新手,我编写了这个 C 程序,让用户输入一年中的某一天,作为返回,程序将输出月份以及该月的哪一天。该程序运行良好,但我现在想简化该程序。我知道我需要一个循环,但我不知道如何去做。这是程序
我一直在努力找出我的代码有什么问题。这个想法是创建一个小的画图程序,并有红色、绿色、蓝色和清除按钮。我有我能想到的一切让它工作,但无法弄清楚代码有什么问题。程序打开,然后立即关闭。 import ja
我想安装screen,但是接下来我应该做什么? $ brew search screen imgur-screenshot screen
我有一个在服务器端工作的 UDP 套接字应用程序。为了测试服务器端,我编写了一个简单的 python 客户端程序,它发送消息“hello world how are you”。服务器随后应接收消息,将
我有一个 shell 脚本,它运行一个 Python 程序来预处理一些数据,然后运行一个 R 程序来执行一些长时间运行的任务。我正在学习使用 Docker 并且我一直在运行 FROM r-base:l
在 Linux 中。我有一个 c 程序,它读取一个 2048 字节的文本文件作为输入。我想从 Python 脚本启动 c 程序。我希望 Python 脚本将文本字符串作为参数传递给 c 程序,而不是将
对于一个类,我被要求编写一个 VHDL 程序,该程序接受两个整数输入 A 和 B,并用 A+B 替换 A,用 A-B 替换 B。我编写了以下程序和测试平台。它完成了实现和行为语法检查,但它不会模拟。尽
module Algorithm where import System.Random import Data.Maybe import Data.List type Atom = String ty
我想找到两个以上数字的最小公倍数 求给定N个数的最小公倍数的C++程序 最佳答案 int lcm(int a, int b) { return (a/gcd(a,b))*b; } 对于gcd,请查看
这个程序有错误。谁能解决这个问题? Error is :TempRecord already defines a member called 'this' with the same paramete
当我运行下面的程序时,我在 str1 和 str2 中得到了垃圾值。所以 #include #include #include using namespace std; int main() {
这是我的作业: 一对刚出生的兔子(一公一母)被放在田里。兔子在一个月大时可以交配,因此在第二个月的月底,每对兔子都会生出两对新兔子,然后死去。 注:在第0个月,有0对兔子。第 1 个月,有 1 对兔子
我编写了一个程序,通过对字母使用 switch 命令将十进制字符串转换为十六进制,但是如果我使用 char,该程序无法正常工作!没有 switch 我无法处理 9 以上的数字。我希望你能理解我,因为我
我是 C++ 新手(虽然我有一些 C 语言经验)和 MySQL,我正在尝试制作一个从 MySQL 读取数据库的程序,我一直在关注这个 tutorial但当我尝试“构建”解决方案时出现错误。 (我正在使
仍然是一个初学者,只是尝试使用 swift 中的一些基本函数。 有人能告诉我这段代码有什么问题吗? import UIKit var guessInt: Int var randomNum = arc
我正在用 C++11 编写一个函数,它采用 constant1 + constant2 形式的表达式并将它们折叠起来。 constant1 和 constant2 存储在 std::string 中,
我用 C++ 编写了这段代码,使用运算符重载对 2 个矩阵进行加法和乘法运算。当我执行代码时,它会在第 57 行和第 59 行产生错误,非法结构操作(两行都出现相同的错误)。请解释我的错误。提前致谢:
我是 C++ 的初学者,我想编写一个简单的程序来交换字符串中的两个字符。 例如;我们输入这个字符串:“EXAMPLE”,我们给它交换这两个字符:“E”和“A”,输出应该类似于“AXEMPLA”。 我在
我需要以下代码的帮助: 声明 3 个 double 类型变量,每个代表三角形的三个边中的一个。 提示用户为第一面输入一个值,然后 将用户的输入设置为您创建的代表三角形第一条边的变量。 将最后 2 个步
我是新来的,如果问题不好请见谅 任务:将给定矩阵旋转180度 输入: 1 4 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 输出: 16 15 14 13 12 11
我是一名优秀的程序员,十分优秀!