NSIS - 如何在一个子节中实现三个相互排斥的部分

NSIS - How to implement three Mutually Exclusive Sections within a SubSection

我有一个简单的 NSIS 脚本,它基于我在 NSIS Mutually Exclusive Sections 上找到的以下源代码。我面临的问题是我无法实现三个相互排斥的部分而不是一个。

第 0 节是独立的。

对于第 1、2 和 3 部分,我需要让它们相互排斥。能够同时 select none 个或一个 selected。

如果您测试该示例,当您 select:

时它似乎运行良好

当您在完成第 3 部分 select 之后继续 select 选项然后转到 select 第 2 部分和第 1 部分时,问题就开始了。或者如果您尝试这样做随机 select 离子 select 离子被弄乱了。

我无法在 SubSection 中的三个部分之间实现这种互斥。谁能给我一些启发?

非常感谢。

谢谢,

这是我到目前为止修改的脚本:

# Example to control section selection.
# It allows only one of three sections to be selected at any
# given time, but unlike one-section, it allows non of them 
# to be selected as well.
#

!include Sections.nsh
!include LogicLib.nsh

Name example
OutFile "mutually exclusive.exe"

ComponentText "please choose zero or one but the default"

SubSection /e "Test" SSEC00
    Section /o "Test Sec 0" sec0
    SectionEnd

    Section /o "#2 and #3 unselected" sec1
    SectionEnd

    Section /o "#1 and #3 unselected" sec2
    SectionEnd

    Section /o "#1 and #2 unselected" sec3
    SectionEnd
SubSectionEnd

Function .onInit
  Push [=10=]

  SectionGetFlags ${sec1} [=10=]
  IntOp [=10=] [=10=] & ${SECTION_OFF}
  SectionSetFlags ${sec1} [=10=]

  SectionGetFlags ${sec2} [=10=]
  IntOp [=10=] [=10=] & ${SECTION_OFF}
  SectionSetFlags ${sec2} [=10=]

  SectionGetFlags ${sec3} [=10=]
  IntOp [=10=] [=10=] & ${SECTION_OFF}
  SectionSetFlags ${sec3} [=10=]

  Pop [=10=]
FunctionEnd

Function .onSelChange
    Push [=10=]

    ${If} ${SectionIsSelected} ${sec1}
    ${OrIf} ${SectionIsSelected} ${sec2}
    ${OrIf} ${SectionIsSelected} ${sec3}

        StrCmp $R9 ${sec1} check_sec2  # If last selection was sec1 goto check_sec2
        StrCmp $R9 ${sec2} check_sec3  # If last selection was sec2 goto check_sec3
        StrCmp $R9 ${sec3} check_sec1

        check_sec1:

        SectionGetFlags ${sec1} [=10=]
        IntOp [=10=] [=10=] & ${SF_SELECTED}
        IntCmp [=10=] ${SF_SELECTED} 0 Seldone Seldone

        StrCpy $R9 ${sec1}
        SectionGetFlags ${sec2} [=10=]
        IntOp [=10=] [=10=] & ${SECTION_OFF}
        SectionSetFlags ${sec2} [=10=]

        SectionGetFlags ${sec3} [=10=]
        IntOp [=10=] [=10=] & ${SECTION_OFF}
        SectionSetFlags ${sec3} [=10=]
        Goto Seldone

        check_sec2:

        SectionGetFlags ${sec2} [=10=]
        IntOp [=10=] [=10=] & ${SF_SELECTED}
        IntCmp [=10=] ${SF_SELECTED} 0 Seldone Seldone

        StrCpy $R9 ${sec2}
        SectionGetFlags ${sec1} [=10=]
        IntOp [=10=] [=10=] & ${SECTION_OFF}
        SectionSetFlags ${sec1} [=10=]

        SectionGetFlags ${sec3} [=10=]
        IntOp [=10=] [=10=] & ${SECTION_OFF}
        SectionSetFlags ${sec3} [=10=]

        check_sec3:

        SectionGetFlags ${sec3} [=10=]
        IntOp [=10=] [=10=] & ${SF_SELECTED}
        IntCmp [=10=] ${SF_SELECTED} 0 Seldone Seldone

        StrCpy $R9 ${sec3}
          SectionGetFlags ${sec1} [=10=]
          IntOp [=10=] [=10=] & ${SECTION_OFF}
          SectionSetFlags ${sec2} [=10=]

          SectionGetFlags ${sec2} [=10=]
          IntOp [=10=] [=10=] & ${SECTION_OFF}
          SectionSetFlags ${sec2} [=10=]

        Goto check_sec1

        Seldone:

    ${EndIf}

    Pop [=10=]
FunctionEnd

在 NSIS v3+ 中,当调用 .onSelChange 时,更改部分的部分 ID 存储在 $0 中,这样更容易获得正确的逻辑:

!include Sections.nsh
!include LogicLib.nsh

ComponentText "please choose zero or one but the default"

SubSection /e "Test" SSEC00
    Section /o "Test Sec 0" sec0
    SectionEnd

    Section /o "#2 and #3 unselected" sec1
    SectionEnd

    Section /o "#1 and #3 unselected" sec2
    SectionEnd

    Section /o "#1 and #2 unselected" sec3
    SectionEnd
SubSectionEnd

Page Components
Page InstFiles

Function .onSelChange
${IfThen} [=10=] = -1 ${|} Return ${|} ; I don't care about InstType changes
${If} [=10=] < ${sec1}
${OrIf} [=10=] > ${sec3}
    Return ; I don't care about other sections
${EndIf}

!macro SelectOnlyMe sid
${IfThen} [=10=] <> ${sid} ${|} !insertmacro UnselectSection ${sid} ${|}
!macroend

!insertmacro SelectOnlyMe ${sec1}
!insertmacro SelectOnlyMe ${sec2}
!insertmacro SelectOnlyMe ${sec3}
FunctionEnd

(如果您需要多组相互排斥的部分,您可以将 "if/orif" 范围检查作为辅助宏的一部分)