Интерфейс приложения 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.

Другие вопросы по тегам