Интерфейс приложения Bootstrapper - Как перемещаться между страницами
Я пишу приложение Bootstrapper и хочу создать для него пользовательский интерфейс с помощью приложения WixStandardBootstrapperApplication. Я хочу, чтобы пользовательский интерфейс был таким, чтобы на первой странице (страница установки) я видел стандартное лицензионное соглашение и флажок, который говорит, что я принимаю, и кнопку для перехода на следующую страницу (страница параметров), которая должна быть включена только после того, как я установил флажок, На следующей странице я перечисляю некоторый текст и хочу иметь еще один флажок, который снова говорит, что я принимаю, и кнопку "Установить", которая становится активной только после того, как я установил флажок.
<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, но он не перечисляет различные опции для флажков или кнопок.
Любые предложения приветствуются. Не стесняйтесь спрашивать, если что-то неясно. Заранее благодарны за Вашу помощь.
1 ответ
Для этого вам нужно вникнуть в код для вашей начальной загрузки приложения (WixStdBootstrapperApplication.cpp).
К счастью, вы основываетесь на приложении WixStdBootstrapperApplication, которое я потратил довольно много времени на знакомство.
Первое, что вам нужно сделать, это поместить EulaAcceptCheckbox обратно на страницу с действительным Eula. Когда вы собираетесь управлять включением / отключением элементов пользовательского интерфейса, вам нужно сделать это из кода загрузочного приложения. БА владеет пользовательским интерфейсом.
Теперь нам нужно изменить поведение этого EulaAcceptCheckbox, чтобы он включал / отключал OptionsButton.
В WndProc мы обрабатываем все сообщения, генерируемые пользователем, когда они нажимают на кнопку, прокручивают или делают что-либо. Под WM_COMMAND у нас есть переключатель, основанный на LOWORD(wParam), который является идентификатором элемента управления, который вызвал сообщение.
Найдите "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);
}
Выглядит супер просто, верно? Здесь вам просто нужно изменить WIXSTDBA_CONTROL_INSTALL_BUTTON на WIXSTDBA_CONTROL_OPTIONS_BUTTON
Нам также необходимо установить для кнопки "Параметры" значение по умолчанию отключено. Для этого мы заходим в "OnChangeState" и ищем if для 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);
}
}
Здесь мы удалили элементы с повышенными правами, так как это идет на кнопку установки и вместо этого включаем / отключаем кнопку параметров в зависимости от того, определена ли она в теме и установлен ли флажок принятия или нет.
Далее вам нужно добавить способ найти новый флажок OptionsPage.
Вы должны иметь enum в вашем файле cpp
enum WIXSTDBA_CONTROL
Это должно быть заказано в средствах управления на страницах. Здесь вам нужно будет добавить новую запись для вашего нового элемента управления флажка Параметры, возможно, WIXSTDBA_CONTROL_OPTIONS_CHECKBOX
Ниже этого перечисления у вас будет 2-й массив
static THEME_ASSIGN_CONTROL_ID vrgInitControls[] =
Здесь вам нужно будет добавить новую запись, которая будет вставлена в то же место, куда вы вставили свой enum. Вставленный элемент массива должен выглядеть следующим образом
{ 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 в ваше приложение начальной загрузки так же, как OnClickAcceptCheckbox ()
void OnClickOptionsCheckbox()
{
BOOL fAccepted = ThemeIsControlChecked(m_pTheme, WIXSTDBA_CONTROL_OPTIONS_CHECKBOX);
ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON, fAccepted);
}
Наконец, нам нужно добавить llElevated материал, который мы удалили из случая WIXSTDBA_PAGE_INSTALL OnChangeState, в 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);
}
}
Есть несколько вещей, которые я бы по-прежнему изменил в этой реализации, но я бы настоятельно рекомендовал попробовать разобраться в том, что делает приложение начальной загрузки и как оно работает.
Если вы хотите изменить поведение пользовательского интерфейса во время установки, вам необходимо ознакомиться с кодом здесь. Вы можете добавлять новые страницы, добавлять элементы управления и устанавливать переменные вместе с некоторыми другими вещами.
Если это кажется большой работой (определенно, я сам все это выяснил), подумайте, нужен ли вам этот тип поведения вместо поведения по умолчанию одной из стандартных тем wixstdba.