This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Extra! Basic Dialog box manipulation

I need to have cascading DropListBox's for a menu that builds a string. For example if DropListBox1 has three plus options it will display DropListBox2 to DropListBox4 below it depending on selection. Each subsequent DropListBox will need to hide/reveal the appropriate DropListBox selection.  I'm unsure if this would best be done by having multiple sub DropListBox's and have them display or hide depending on previous menu selection like the bad example image or if I should propagate each DropListBox with an array.   Which would be more efficient?  I've been unsuccessful in both hiding / revealing and propagating with arrays.  The goal of the dialog box is to create a string that it sends to the terminal. I'm an end user, not a developer but I am putting in earnest effort to learn.

My current partially functional dialog looks like:

Bad Example:

Labels:

Mainframe Access
Parents
  • 0

    I've decided to go with a two dimensional array, but I'm stuck on how to propagate the DropDownList from an Array range. Selecting a single item like arr_G(5, 0) works fine, but how do i add the range of arr_G(0, 0) to arr_G(5, 0) to "DropListBoxCate"?

    Sub Main
    Dim arr_G(5, 93) As Variant ' 93 actual count on some subjects

    arr_G(0, 0) = "Category 0"
      arr_G(0, 1) = "Subject 1"
      arr_G(0, 2) = "Subject 2"
      arr_G(0, 3) = "Subject 3"
    arr_G(1, 0) = "Category 1"
      arr_G(1, 1) = "Subject 1"
      arr_G(1, 2) = "Subject 2"
      arr_G(1, 3) = "Subject 3"

    arr_G(2, 0) = "Category 2"
      arr_G(2, 1) = "Subject 1"
      arr_G(2, 2) = "Subject 2"
      arr_G(2, 3) = "Subject 3"

    arr_G(3, 0) = "Category 3"
      arr_G(3, 1) = "Subject 1"
      arr_G(3, 2) = "Subject 2"
      arr_G(3, 3) = "Subject 3"
    arr_G(4, 0) = "Category 4"
      arr_G(4, 1) = "Subject 1"
      arr_G(4, 2) = "Subject 2"
      arr_G(4, 3) = "Subject 3"
    arr_G(5, 0) = "Category 5"
      arr_G(5, 1) = "Subject 1"
      arr_G(5, 2) = "Subject 2"
      arr_G(5, 3) = "Subject 3"


    Begin Dialog AddDialog 215, 74, "command"
    DropListBox  35, 1, 103, 16, ""+chr$(9)+arr_G(0, 0)+chr$(9)+arr_G(1, 0)+chr$(9)+arr_G(2, 0)+chr$(9)+arr_G(3, 0)+chr$(9)+arr_G(4, 0)+chr$(9)+arr_G(5, 0), .DropListBoxCate
    OkButton 148, 21, 50, 14
    CancelButton 150, 2, 50, 14
    Text 2, 4, 31, 13, "Category"
    Text 2, 20, 25, 10, "Subject"
    DropListBox 36, 20, 103, 16, arr_G(5, 1), .DropListBoxSubj
    Text 3, 35, 19, 10, "Page"
    DropListBox 36, 38, 103, 16, ""+chr$(9)+"1"+chr$(9)+"2"+chr$(9)+"3"+chr$(9)+"4"+chr$(9)+"5"+chr$(9)+"6"+chr$(9)+"7"+chr$(9)+"8"+chr$(9)+"9", .DropListBoxPage
    End Dialog

    dim dlg as AddDialog
    ret% = Dialog(dlg)

    End Sub

  • 0   in reply to 

    Hi David, 

    I'm having a look.

    In order to dynamically change the various options you have to create a Function to handle Dialog events.

    In your Begin Dialog statement you append a    , .DialogHandler     after the TitleBar string.

    e.g.
          Begin Dialog StringBuilder 374, 182, "My Dynamic Dialog", .DialogHandler

    Then you create a function to handle the events.

    e.g.
          Function DialogHandler(id$, action%, suppvalue&)

               Select Case action%
                          Case 1 'initialize dialog controls
                          Case 2 'button was pressed, radio, checkbox changed#
                          Case 3 'text or combo box changed
                          Case 4 'control focus changed
                          Case 5 'idle
               End Select
          End Function

    So you initialise your Category drop down in Case 1, then when you select your Category in the first drop down this will trigger Case 2 (where you execute your code based on the value selected in Category drop down), selecting a value in the Subject list with also trigger Case 2 and you then populate your Page values based on the Subject selected in the Subject control.

    I should have something by tomorrow. 

    Note: This is really way beyond scope for the forum and really you should be turning towards our consultants. But given the lack of a sample on here I think we should go ahead and get one out there.

    Tom

  • 0 in reply to   

    Tom,

      Thanks for pointing out that I'm posting these type of questions to the wrong forum. I'll redirect my questions to Stack Overflow if too far off focus for this group.  I was actually just about to delete my post because I found all the reference information I needed on the link https://portal.microfocus.com/s/article/KM000008384?language=en_US you provided me some time ago.  The manuals help some, but my limited scope of knowledge makes them difficult to use as reference, however the eb-samples files had the example named  DialogUpdates.ebm that gave me the pointers and syntax I needed to know.  I've restructured my code with what I learned from the sample and its working perfectly. Its a bit sloppy at the moment, but after I clean it up, I'll post in this discussion thread for any other end users overstepping their areas of responsibility like myself.   Each of the questions you have answered previously have helped point me in the right direction and bettered my understanding.

    Thank You,

    David 

  • Verified Answer

    +1   in reply to 

    Hi David, 

    It's refreshing to see that you pushed ahead and are willing to do the donkey work. Extra! Basic dialogs are not for the faint of heart (or perseverance). Handling the events is not trivial and hence to recommendation to use consulting services.
     
    As for Stack Overflow, it is a great resource, I often use it when I'm trying to figure out how to use Win32API calls in both Extra! Basic and 64-bit VBA.

    I had a play with this and this is what I came up with. I'm using an ini file to store the Category/Subject and Page info. My ini is located at c:\temp\StringBuilderIni.ini (set in the GetList function below)

    My ini looks like this, where the [ListCat] stores a list of all the Categories (and is loaded at initialisation, with the default Category being the first in the list), [My Categories] stores info for each category listed in the [ListCat] section (and the subject associated with the first Category as loaded at initialisation) and finally there are individual Category section which list the number of pages associated with each Subject. 

        [ListCat]
        MyCategories=Category1, Category2, Category3, Category4

        [MyCategories]
        Category1=SubjectA,SubjectB,SubjectC
        Category2=SubjectB,SubjectC,SubjectD
        Category3= SubjectD, SubjectE
        Category4=SubjectV, SubjectW,SubjectX,SubjectY,SubjectZ

        [Category1]
        SubjectA=8
        SubjectB=2
        SubjectC=7

        [Category2]
        SubjectB=8
        SubjectC=14
        SubjectD=12

        [Category3]
        SubjectD=7
        SubjectE=4

        [Category4]
        SubjectV=13
        SubjectW=12
        SubjectX=10
        SubjectY=30
        SubjectZ=93

    Then in Extra Basic I have the following code.

    ---------------------------------------------------------------------------------------------------------------------------------------

    Declare Function GetPrivateProfileString Lib "KERNEL32" Alias "GetPrivateProfileStringA" _
    (ByVal lpApplicationName as String, ByVal lpKeyName As String, ByVal lpDefault As String, _
    ByVal lpReturenedString as String, ByVal nSize as Long, ByVal lpFileName as String) as Long

    Declare Function DialogHandler(ID$, Action%, SuppVal&) as Integer
    Declare Function GetList(Section as String, Key as String) as String

    ' NOTE it is very important to define the buffer size when
    ' calling a Winapi function, if you do not define it defaults
    ' to zero and then your Winapi call will not work. It will
    ' always return zero.

    Const Buffer_size = 255
    Const MySeperator = ","


    Dim MyCategory() as String
    Dim MySubject() as String
    Dim MyPage() as String
    Dim MyOptions() as String

    Sub Main

    Begin Dialog StringBuilder 374, 182, "My Dynamic Dialog", .DialogHandler
    DropListBox 4, 6, 81, 16, "Category1", .Category
    StaticComboBox 89, 6, 112, 153, "", .Subject
    StaticComboBox 200, 6, 102, 154, "", .Page
    PushButton 311, 4, 49, 17, "&Send String", .SendString
    CancelButton 311, 26, 49, 17
    End Dialog

    Dim myStringBuilder as StringBuilder, ret as Integer
    ret% = Dialog(myStringBuilder)

    End Sub

    Function DialogHandler(id$, action%, suppvalue&)

    Dim myList as String, x as Integer, SeperatorLocation as Integer, MyPageCount as String, PageCount as Integer

    select case action%
    Case 1 'initialize dialog controls

    MyList = GetList("ListCat", "MyCategories")
    x=0
    If InStr(1, MyList, MySeperator) = 0 then
    ReDim Preserve myCategory(0)
    myCategory(0) = Trim(MyList)
    Else
    Do While InStr(1, MyList, MySeperator) > 1
    myList = LTrim(MyList)
    ReDim Preserve MyCategory(x)
    SeperatorLocation = InStr(1, MyList, MySeperator)
    myCategory(x)=Left(MyList, SeperatorLocation-1)
    MyList = Right(MyList, Len(MyList)-SeperatorLocation)
    x=x+1
    Loop
    ReDim Preserve myCategory(x)
    myCategory(x) = LTrim(Right((MyList), Len(MyList)))
    End If
    DlgListBoxArray DlgControlID("Category"), myCategory
    DlgValue DlgControlID("Category"),0
    MyList = GetList("MyCategories", myCategory(DlgValue(DlgControlID("Category"))))
    x=0
    If InStr(1, MyList, MySeperator) = 0 then
    ReDim Preserve MySubject(0)
    MySubject(0) = Trim(MyList)
    Else
    Do While InStr(1, MyList, MySeperator) > 1
    myList = LTrim(MyList)
    ReDim Preserve MySubject(x)
    SeperatorLocation = InStr(1, MyList, MySeperator)
    MySubject(x)=Left(MyList, SeperatorLocation-1)
    MyList = Right(MyList, Len(MyList)-SeperatorLocation)
    x=x+1
    Loop
    ReDim Preserve MySubject(x)
    MySubject(x) = Ltrim(Right((MyList), Len(MyList)))
    End If
    DlgListBoxArray DlgControlID("Subject"), MySubject
    DlgListBoxArray DlgControlID("Page"), myOptions

    Case 2 'button was pressed, radio, checkbox changed

    Select Case id$
    Case "Category"
    MyList = GetList("MyCategories", myCategory(DlgValue(DlgControlID("Category"))))
    x=0
    If InStr(1, MyList, MySeperator) = 0 then
    ReDim Preserve MySubject(0)
    MySubject(0) = Trim(MyList)
    Else
    Do While InStr(1, MyList, MySeperator) > 1
    myList = LTrim(MyList)
    ReDim Preserve MySubject(x)
    SeperatorLocation = InStr(1, MyList, MySeperator)
    MySubject(x)=Left(MyList, SeperatorLocation-1)
    MyList = Right(MyList, Len(MyList)-SeperatorLocation)
    x=x+1
    Loop
    ReDim Preserve MySubject(x)
    MySubject(x) = Ltrim(Right((MyList), Len(MyList)))
    End If
    DlgListBoxArray DlgControlID("Subject"), MySubject
    DlgListBoxArray DlgControlID("Page"), myOptions

    Case "Subject"
    MyPageCount = GetList(myCategory(DlgValue(DlgControlID("Category"))), mySubject(DlgValue(DlgControlID("Subject"))))
    PageCount = CInt(MyPageCount)
    ReDim Preserve MyPage(PageCount-1)
    For i = 0 to PageCount -1
    MyPage(i)= i+1
    Next i
    DlgListBoxArray DlgControlID("Page"), MyPage

    Case "SendString"
    If DlgValue(DlgControlID("Category")) = -1 or DlgValue(DlgControlID("Subject")) = -1 or DlgValue(DlgControlID("Page")) = -1 then
    DialogHandler = TRUE ' 'prevent MainDialog from closing
    Else
    Msgbox myCategory(DlgValue(DlgControlID("Category"))) & ":" & mySubject(DlgValue(DlgControlID("Subject"))) & ":" & myPage(DlgValue(DlgControlID("Page"))), 64, "My Selected bits"
    DialogHandler = TRUE ' 'prevent MainDialog from closing
    End If
    Case Else


    End Select

    'Other cases are available to handle changes
    'in textboxes or lists - see help for "begin dialog".
    Case 3 'text or combo box changed
    Case 4 'control focus changed
    Case 5 'idle

    End Select


    End Function


    Function GetList(Section as String, Key as String) as Variant

    Dim x, nSize as long
    Dim FileName as string, Nodename as string, MyList as String

    x = -999

    FileName = "c:\temp\StringBuilderIni.ini"
    Dim Default as String
    Default = "notFound"
    Dim RetStr as String*Buffer_size

    ' Initialize the buffer so it will return more than zero
    ' bytes
    '
    nsize = Buffer_size

    x = GetPrivateProfileString(Section, Key, Default, RetStr, nSize, FileName)
    MyList = mid$(RetStr, 1, x)

    GetList = MyList

    End Function

    ---------------------------------------------------------------------------------------------------------------------------------------

    It likely works in a similar fashion to what you now have, but it demo's how to avoid the multi-dimensional array and it enables one to change the Categories, Subjects and Pages without having to touch the macro.

    Looking forward to seeing what you eventually end up with.

    Tom

Reply
  • Verified Answer

    +1   in reply to 

    Hi David, 

    It's refreshing to see that you pushed ahead and are willing to do the donkey work. Extra! Basic dialogs are not for the faint of heart (or perseverance). Handling the events is not trivial and hence to recommendation to use consulting services.
     
    As for Stack Overflow, it is a great resource, I often use it when I'm trying to figure out how to use Win32API calls in both Extra! Basic and 64-bit VBA.

    I had a play with this and this is what I came up with. I'm using an ini file to store the Category/Subject and Page info. My ini is located at c:\temp\StringBuilderIni.ini (set in the GetList function below)

    My ini looks like this, where the [ListCat] stores a list of all the Categories (and is loaded at initialisation, with the default Category being the first in the list), [My Categories] stores info for each category listed in the [ListCat] section (and the subject associated with the first Category as loaded at initialisation) and finally there are individual Category section which list the number of pages associated with each Subject. 

        [ListCat]
        MyCategories=Category1, Category2, Category3, Category4

        [MyCategories]
        Category1=SubjectA,SubjectB,SubjectC
        Category2=SubjectB,SubjectC,SubjectD
        Category3= SubjectD, SubjectE
        Category4=SubjectV, SubjectW,SubjectX,SubjectY,SubjectZ

        [Category1]
        SubjectA=8
        SubjectB=2
        SubjectC=7

        [Category2]
        SubjectB=8
        SubjectC=14
        SubjectD=12

        [Category3]
        SubjectD=7
        SubjectE=4

        [Category4]
        SubjectV=13
        SubjectW=12
        SubjectX=10
        SubjectY=30
        SubjectZ=93

    Then in Extra Basic I have the following code.

    ---------------------------------------------------------------------------------------------------------------------------------------

    Declare Function GetPrivateProfileString Lib "KERNEL32" Alias "GetPrivateProfileStringA" _
    (ByVal lpApplicationName as String, ByVal lpKeyName As String, ByVal lpDefault As String, _
    ByVal lpReturenedString as String, ByVal nSize as Long, ByVal lpFileName as String) as Long

    Declare Function DialogHandler(ID$, Action%, SuppVal&) as Integer
    Declare Function GetList(Section as String, Key as String) as String

    ' NOTE it is very important to define the buffer size when
    ' calling a Winapi function, if you do not define it defaults
    ' to zero and then your Winapi call will not work. It will
    ' always return zero.

    Const Buffer_size = 255
    Const MySeperator = ","


    Dim MyCategory() as String
    Dim MySubject() as String
    Dim MyPage() as String
    Dim MyOptions() as String

    Sub Main

    Begin Dialog StringBuilder 374, 182, "My Dynamic Dialog", .DialogHandler
    DropListBox 4, 6, 81, 16, "Category1", .Category
    StaticComboBox 89, 6, 112, 153, "", .Subject
    StaticComboBox 200, 6, 102, 154, "", .Page
    PushButton 311, 4, 49, 17, "&Send String", .SendString
    CancelButton 311, 26, 49, 17
    End Dialog

    Dim myStringBuilder as StringBuilder, ret as Integer
    ret% = Dialog(myStringBuilder)

    End Sub

    Function DialogHandler(id$, action%, suppvalue&)

    Dim myList as String, x as Integer, SeperatorLocation as Integer, MyPageCount as String, PageCount as Integer

    select case action%
    Case 1 'initialize dialog controls

    MyList = GetList("ListCat", "MyCategories")
    x=0
    If InStr(1, MyList, MySeperator) = 0 then
    ReDim Preserve myCategory(0)
    myCategory(0) = Trim(MyList)
    Else
    Do While InStr(1, MyList, MySeperator) > 1
    myList = LTrim(MyList)
    ReDim Preserve MyCategory(x)
    SeperatorLocation = InStr(1, MyList, MySeperator)
    myCategory(x)=Left(MyList, SeperatorLocation-1)
    MyList = Right(MyList, Len(MyList)-SeperatorLocation)
    x=x+1
    Loop
    ReDim Preserve myCategory(x)
    myCategory(x) = LTrim(Right((MyList), Len(MyList)))
    End If
    DlgListBoxArray DlgControlID("Category"), myCategory
    DlgValue DlgControlID("Category"),0
    MyList = GetList("MyCategories", myCategory(DlgValue(DlgControlID("Category"))))
    x=0
    If InStr(1, MyList, MySeperator) = 0 then
    ReDim Preserve MySubject(0)
    MySubject(0) = Trim(MyList)
    Else
    Do While InStr(1, MyList, MySeperator) > 1
    myList = LTrim(MyList)
    ReDim Preserve MySubject(x)
    SeperatorLocation = InStr(1, MyList, MySeperator)
    MySubject(x)=Left(MyList, SeperatorLocation-1)
    MyList = Right(MyList, Len(MyList)-SeperatorLocation)
    x=x+1
    Loop
    ReDim Preserve MySubject(x)
    MySubject(x) = Ltrim(Right((MyList), Len(MyList)))
    End If
    DlgListBoxArray DlgControlID("Subject"), MySubject
    DlgListBoxArray DlgControlID("Page"), myOptions

    Case 2 'button was pressed, radio, checkbox changed

    Select Case id$
    Case "Category"
    MyList = GetList("MyCategories", myCategory(DlgValue(DlgControlID("Category"))))
    x=0
    If InStr(1, MyList, MySeperator) = 0 then
    ReDim Preserve MySubject(0)
    MySubject(0) = Trim(MyList)
    Else
    Do While InStr(1, MyList, MySeperator) > 1
    myList = LTrim(MyList)
    ReDim Preserve MySubject(x)
    SeperatorLocation = InStr(1, MyList, MySeperator)
    MySubject(x)=Left(MyList, SeperatorLocation-1)
    MyList = Right(MyList, Len(MyList)-SeperatorLocation)
    x=x+1
    Loop
    ReDim Preserve MySubject(x)
    MySubject(x) = Ltrim(Right((MyList), Len(MyList)))
    End If
    DlgListBoxArray DlgControlID("Subject"), MySubject
    DlgListBoxArray DlgControlID("Page"), myOptions

    Case "Subject"
    MyPageCount = GetList(myCategory(DlgValue(DlgControlID("Category"))), mySubject(DlgValue(DlgControlID("Subject"))))
    PageCount = CInt(MyPageCount)
    ReDim Preserve MyPage(PageCount-1)
    For i = 0 to PageCount -1
    MyPage(i)= i+1
    Next i
    DlgListBoxArray DlgControlID("Page"), MyPage

    Case "SendString"
    If DlgValue(DlgControlID("Category")) = -1 or DlgValue(DlgControlID("Subject")) = -1 or DlgValue(DlgControlID("Page")) = -1 then
    DialogHandler = TRUE ' 'prevent MainDialog from closing
    Else
    Msgbox myCategory(DlgValue(DlgControlID("Category"))) & ":" & mySubject(DlgValue(DlgControlID("Subject"))) & ":" & myPage(DlgValue(DlgControlID("Page"))), 64, "My Selected bits"
    DialogHandler = TRUE ' 'prevent MainDialog from closing
    End If
    Case Else


    End Select

    'Other cases are available to handle changes
    'in textboxes or lists - see help for "begin dialog".
    Case 3 'text or combo box changed
    Case 4 'control focus changed
    Case 5 'idle

    End Select


    End Function


    Function GetList(Section as String, Key as String) as Variant

    Dim x, nSize as long
    Dim FileName as string, Nodename as string, MyList as String

    x = -999

    FileName = "c:\temp\StringBuilderIni.ini"
    Dim Default as String
    Default = "notFound"
    Dim RetStr as String*Buffer_size

    ' Initialize the buffer so it will return more than zero
    ' bytes
    '
    nsize = Buffer_size

    x = GetPrivateProfileString(Section, Key, Default, RetStr, nSize, FileName)
    MyList = mid$(RetStr, 1, x)

    GetList = MyList

    End Function

    ---------------------------------------------------------------------------------------------------------------------------------------

    It likely works in a similar fashion to what you now have, but it demo's how to avoid the multi-dimensional array and it enables one to change the Categories, Subjects and Pages without having to touch the macro.

    Looking forward to seeing what you eventually end up with.

    Tom

Children
  • 0 in reply to   

    WOW, I'm floored by your response. I was hoping for a best case scenario to be nudged in the right direction, but you went way above the call of duty.   With the exception of an INI to provide the data, which I really like by the way.  My code is not exactly identical but surprisingly similar to yours. Not going to lie, seeing the similarities in the code makes me a little proud of myself. LOL.   I just recently moved from railroad electrician to railroad foreman on nights shift, so my time to code is typically five minutes here and there over days, but I'll put my solution up when I'm finished.  I'm working with my live data and need to scrub it to generic topics before posting.  Again, I can’t believe the breath of your response, that's definitely not what I was expecting.  I cant thank you enough.

  • 0 in reply to   

    Tom,

          Sorry I've not been back to post my version of the code yet.  As a foreman and not a developer its often difficult to find time for coding at work. Today I committed time to my personal project on my day off and after finally getting to really play with the code find your code to be substantially more efficient. I've abandoned my array and I'm reworking my implementation around your much appreciated example. I have found one issue that I can’t seem to grasp. Using an array my DropListBox could handle the number of menu items I needed, but when reading from the INI file I'm limited to approximately 270 characters per line then it self-truncates.  I’ve worked around this by adding  “Category2 Part 1”, “Category2 Part 2”, etc. to subjects in the INI keeping each line under 270 characters which works. I’m just curious why it truncates the line when reading the INI file.

    Example:

        [MyCategories]
        Category1=SubjectA,SubjectB,SubjectC (this line works)
        Category2=SubjectB,SubjectC,SubjectD, …(lots of items, in excess of 270 characters)…, SubjectGG (this line does not work)