Verständnisfrage zu Strukturen

Für allgemeine Fragen zur Programmierung mit PureBasic.
kmais
Beiträge: 45
Registriert: 09.02.2017 13:54

Verständnisfrage zu Strukturen

Beitrag von kmais »

Ich habe folgende Struktur:

Code: Alles auswählen

Structure Child
  Name.s 
  wdgId.i 
  RefStrukt.i 
  StartX.i  
  StartY.i  
  StartW.i  
  StartH.i     
  Type.i  
  ParentId.i 
  RefParentStrukt.i 
  isContainer.i 
  ParentWin.i
  Text.s                 
  textFont.i  
  textSize.i  
  textAttribut.i  
EndStructure
Wenn ich die Reihenfolge der Strukturelemente ändere in:

Code: Alles auswählen

Structure Child
  Name.s 
  wdgId.i 
  RefStrukt.i 
  Type.i  
  ParentId.i 
  RefParentStrukt.i 
  isContainer.i 
  ParentWin.i
  Text.s                 
  textFont.i  
  textSize.i  
  textAttribut.i  
  StartX.i  
  StartY.i  
  StartW.i  
  StartH.i     
EndStructure
ändert sich das Laufzeitverhalten des Programms.
In diesem Fall wird eine Zeigervariable vom obigen Typ in einer Rekursion anders referenziert (da fehlt mir derzeit noch der Überblick).
Es ist mir völlig schleierhaft, wie die Reihenfolge innerhalb einer Struktur dies bewerkstelligen soll.

// Edit: Code-Tags hinzugefügt (Kiffi)
Benutzeravatar
mk-soft
Beiträge: 3701
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Verständnisfrage zu Strukturen

Beitrag von mk-soft »

Bitte Code-Tags verwenden.

Ich sehe hier keine rekursive Verschaltung. Zu wenig info...
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
kmais
Beiträge: 45
Registriert: 09.02.2017 13:54

Re: Verständnisfrage zu Strukturen

Beitrag von kmais »

Das ist jede Menge Code. Da muss ich mal eine Zusammenfassung machen und posten.
Beim weiteren Austesten habe ich bemerkt, dass das Problem nur unter Linux mit GTK2 auftritt.
GTK3 und Qt laufen problemlos. Ebenso Windows.
kmais
Beiträge: 45
Registriert: 09.02.2017 13:54

Re: Verständnisfrage zu Strukturen

Beitrag von kmais »

Hier etwas abgespeckter Code, aber darin nachvollziehbar.

Ganz oben im Modul "Container" befinden sich 2 Child Strukturen.
Wird die erste (im Moment aktive) verwendet, kommt es zu dem Fehler.
Wird die zweite (darunter) verwendet, entsteht kein Error, bzw. Warnung.
Der Grund für den Error ist, dass im letzten Rekursionsschritt ein Null-Zeiger übergeben wird.
Die Rekursions wird in "ModWdgClass" in der Proc. "checkName(Name.s)" angestoßen in der
Procedure WdgHandler(Map WdgMap.widget())

Seltsam, dass die Anordnung der Elemente in der Struktur den Error auslöst.

Hier der Code:

Code: Alles auswählen

; ==================================== Modul Container ==========================================================

DeclareModule Container            

  Enumeration Container
    #getChildId
    #getChildName
    #PB_ContainerType_Panel
  EndEnumeration
  
  Structure widget 
    Name.s : wdgId.i : RefStrukt.i : StartX.i : StartY.i : StartW.i : StartH.i : Type.i : ParentId.i : RefParentStrukt.i : isContainer.i : ParentWin.i
    x.i : y.i : w.i : h.i : Text.s : Format.s : Verzeichnis.s : Url.s : FirstDate.i : CellW.i : cellH.i : imageId.i
    Min.i : Max.i : pgBFarbe.i : ScrollW.i :  ScrollH.i : ScrollStep.i : sLaenge.i : sc1.i : sc2.i
    Gadget1.i : Gadget2.i : TabCount.i : flag1.i : flag2.i : flag3.i : flag4.i : flag5.i : flag6.i  : Farbe.i                        
    textFont.i : textSize.i : textAttribut.i : RefCallback.i : Ref1.i : Ref2.i : tempId.s : TabsCount.i
  EndStructure   
  
  Structure Child
    
     Name.s 
     wdgId.i 
     RefStrukt.i 
     Type.i  
     ParentId.i 
     RefParentStrukt.i 
     ParentWin.i
     isContainer.i
     StartX.i  
     StartY.i  
     StartW.i  
     StartH.i 
     Text.s   
     textFont.i  
     textSize.i  
     textAttribut.i  
    EndStructure 
  
;   Structure Child
;     Name.s
;     wdgId.i
;     RefStrukt.i
;     StartX.i                           ; - Key der Map entspricht Gadget-Id im Programm
;     StartY.i                           ; - WinId -> Identifikation des Fensters in welchem das Gadgets sich befindet
;     StartW.i                           ; 
;     StartH.i                           ; -------------------------------------------
;     Text.s                             ; -> Über die Map-Einträge sind Änderung der Fenstergröße auf alle Gadgets problemlos anwendbar
;     textFont.i
;     textSize.i
;     textAttribut.i                        ; 
;     Type.i
;     ParentId.i
;     RefParentStrukt.i
;     isContainer.i
;     ParentWin.i 
;   EndStructure
    
  Structure Container
    Map childMap.Child()   
    Name.s
    wdgId.i
    RefStrukt.i
    StartX.i                           ; - Key der Map entspricht Gadget-Id im Programm
    StartY.i                           ; - WinId -> Identifikation des Fensters in welchem das Gadgets sich befindet
    StartW.i                           ; 
    StartH.i                           ; -------------------------------------------     
    Text.s                                   ; 
    Type.i
    ParentId.i
    RefParentStrukt.i
    isContainer.i
    ParentWin.i
  EndStructure

EndDeclareModule

Module Container
  
EndModule
;===========================================================================================================
;========================================== ModWdgCustom =====================================================


;                                                
; =================================================== Modul TreeByKey =============================================================

DeclareModule TreeByKey
  Enumeration 1001
    #GadgetType_TreeView
  EndEnumeration
  Structure treeParams
    Key.s
    wdgId.i
    Text.s
    ImageId.i
    Vg.s
    subLevel.i
  EndStructure
  
  Structure treeView
    Map treeIn.treeParams()
    List treeOut.treeParams()
    RefStrukt.i
    StartX.i                           ; - Key der Map entspricht Gadget-Id im Programm
    StartY.i                           ; - WinId -> Identifikation des Fensters in welchem das Gadgets sich befindet
    StartW.i                           ; 
    StartH.i  
    Name.s
    wdgId.i
    ParentWin.i
    ParentId.i
  EndStructure
  

  ArraySizeFlag.i = #False

  Declare createTreeByKey(x,y,w,h,flag1 = #False,flag2 = #False,flag3 = #False,flag4 = #False,flag5 = #False,flag6 = #False)
  Declare TreeAddItem(Map myMap.treeParams(),key.s,Vg.s,Text.s,ImageId.i)
  Declare showTreeExpanded(wdgId)
  Declare parseTreeView(wdgId.i,pBar.i)
  Declare showTreeView(wdgId.i)
  Declare Width(wdgId.i)
  Declare Height(wdgId.i)
  Declare X(wdgId.i)
  Declare Y(wdgId.i)
  Declare EntferneItem(wdgId.i,number.i)
  Declare ClearItems(wdgId.i)
  Declare GetCountItems(wdgId.i)
  Declare.s GetTextByNumber(wdgId.i,number.i)
  Declare.s GetSelectText(wdgId.i)
  Declare GetSublevelbyNumber(wdgId.i,number.i)
  Declare SetTextByNumber(wdgId.i,number.i)
  Declare SetSelectText(wdgId.i)
  Declare GetItemNumber(wdgId.i)
  Declare GetItemStatus(wdgId.i,number.i)
;   Declare.s getKey(wdgId.i)
EndDeclareModule

Module TreeByKey
  
  Procedure Height(wdgId)
    ProcedureReturn GadgetHeight(wdgId.i)
  EndProcedure
  
  Procedure Width(wdgId.i)
    ProcedureReturn GadgetWidth(wdgId)
  EndProcedure
  
  Procedure x(wdgId.i)
    ProcedureReturn GadgetX(wdgId)
  EndProcedure
  
  Procedure y(wdgId.i)
    ProcedureReturn GadgetY(wdgId)
  EndProcedure
  
  Procedure ClearItems(wdgId.i)
    ClearGadgetItems(wdgId)
  EndProcedure
  
  Procedure EntferneItem(wdgId.i,number.i)
    RemoveGadgetItem(wdgId,number)
  EndProcedure
  
  Procedure GetCountItems(wdgId.i)
    ProcedureReturn CountGadgetItems(wdgId)
  EndProcedure
  
  Procedure GetItemNumber(wdgId.i)
    ProcedureReturn GetGadgetState(wdgId)
  EndProcedure
  
  Procedure GetItemStatus(wdgId.i,number.i) ;#PB_Tree_Selected,#PB_Tree_Expanded,#PB_Tree_Collapsed,#PB_Tree_Checked
    ProcedureReturn GetGadgetItemState(wdgId,number);     ;#PB_Tree_Inbetween: If Ergebnis & #PB_Tree_Checked
  EndProcedure
  
  Procedure.s GetTextByNumber(wdgId.i,number.i)
    ProcedureReturn GetGadgetItemText(wdgId,number)
  EndProcedure
  
  Procedure.s GetSelectText(wdgId.i)
    ProcedureReturn GetGadgetText(wdgId)
  EndProcedure
  
  Procedure GetSublevelbyNumber(wdgId.i,number.i)
    ProcedureReturn GetGadgetItemAttribute(wdgId,number,#PB_Tree_SubLevel) ;#PB_Tree_SubLevel
  EndProcedure
  Procedure SetTextByNumber(wdgId.i,number.i)
    SetGadgetItemText(wdgId,number.i,Text.s)
  EndProcedure
  
  Procedure SetSelectText(wdgId.i)
    SetGadgetText(wdgId,Text.s)
  EndProcedure
  
;-----------------------------------------------------------------------------------------------
  
  
  Procedure createTreeByKey(x,y,w,h,flag1 = #False,flag2 = #False,flag3 = #False,flag4 = #False,flag5 = #False,flag6 = #False)
    wdgId = TreeGadget(#PB_Any, x, y, w, h,flag1 | flag2 | flag3| flag4 | flag5 | flag6)
    ProcedureReturn wdgId
  EndProcedure
  
  Procedure TreeAddItem(Map myMap.treeParams(),key.s,Vg.s,Text.s,ImageId.i)
    myMap(key)\Key=key
    myMap(key)\Vg=Vg
    myMap(key)\Text=Text
    myMap(key)\ImageId=ImageID
  EndProcedure
  
  Procedure copyElementMapToListSequentiell(key.s,Map quellMap.treeparams(),List treeOut.treeparams())
    AddElement(treeOut())
    With treeOut()
      \ImageId = quellMap()\ImageId 
      \Key = quellMap(key)\Key
      \wdgId = quellMap(key)\wdgId
      \subLevel = quellMap(key)\subLevel
      \Text = quellMap(key)\Text
      \Vg = quellMap(key)\Vg
    EndWith
  EndProcedure
  
  idCount=0
  subLevel=0
  
  Procedure testUnitKey(List workList.treeParams(),newKey.s)
    If ListSize(workList())>0
      PushListPosition(workList())
      ForEach workList()
        If workList()\Key=newKey
          MessageRequester("App-Meldung","Der Key '" + newKey + "' wird bereits verwendet",#PB_MessageRequester_Ok )
          PopListPosition(workList())
          ProcedureReturn #True
        EndIf
      Next
      PopListPosition(workList())
      ProcedureReturn #False
    EndIf
    ProcedureReturn #False
  EndProcedure
  
  Procedure showTreeExpanded(wdgId)
    For Counter = 0 To CountGadgetItems(wdgId) - 1
      SetGadgetItemState(wdgId, Counter, GetGadgetItemState(wdgId, Counter) | #PB_Tree_Expanded)
    Next
  EndProcedure
  
  Procedure.s GetTreeHeaderList(List treeOut.treeParams())
    ResetList(treeOut())
    NextElement(treeOut())
    If ListSize(treeOut())>=1
      ProcedureReturn treeOut()\Key
    EndIf
  EndProcedure
  
  Procedure GetTreeSizeMap(Map treeIn.treeParams())
    ProcedureReturn MapSize(treeIn())
  EndProcedure

  Procedure parseTree(key.s,Map In.treeParams(), List treeOut.treeParams(),pBar.i)

    NewMap RekurseMap.treeParams() ;jeder Rekursionsschritt benötigt seine eigene map->bei Rek.Rückschritt liegt sonst nicht
    con=CopyMap(In(),RekurseMap())     ;mehr die in diesem Schritt verwendete Map mit deren Elementen vor.
    Shared idCount, subLevel   ;shared, da diese sonst bei Rekursion zurückgesetzt würden.
    copyElementMapToListSequentiell(key,RekurseMap(),treeOut()) ;kopiert aktuellen Key von Map in Liste
    DeleteMapElement(RekurseMap(),key) ;reduziert die Map um die abgearbeiteten Elemene. Nicht notwendig ->reduziert Abarbeitungsaufwand
    ResetMap(RekurseMap())             ;setzt miz "while nextmapelement" die Map an den Anfang, um sie vollständig abzuarbeiten
    While NextMapElement(RekurseMap()) > 0 ;solange noch Elemente in der Map sind
      If RekurseMap()\Vg = key         ;sucht Element mit aktuellen Key als Vorgänger
        idCount=idCount+1          ;Laufvariable bei gefundenem Vorgänger erhöht um eins -> sequentielle Abfolge des Elemente
        subLevel=subLevel+1
        RekurseMap()\subLevel = subLevel
        RekurseMap()\wdgId = idCount
        parseTree(RekurseMap()\Key, RekurseMap(), treeOut(),pBar) ;RekurseMap()\Key -> Vorgänger Id = neuer Key
      EndIf
    Wend                           ;läuft bis nächstes Element = 0 -> Map = abgearbeitet; <> 0 -> setzt Zeiger auf nächstes
    subLevel=subLevel-1                                             ;                                               Element              
    
  EndProcedure
  
  Procedure parseTreeView(*TreeView.treeView,pBar.i)
    
    Shared idCount, subLevel ;,treeViewMap.treeParams()
    idCount=0
    subLevel = 0
    
    With *TreeView
      If GetTreeSizeMap(\treeIn())>=1
        ResetMap(\treeIn())
        NextMapElement(\treeIn())
        ForEach \treeIn()
          If \treeIn()\vg=""
            headKey.s= \treeIn()\Key
            Break
          EndIf
        Next
      Else
        headKey.s=GetTreeHeaderList(\treeOut())
      EndIf
      ClearList(\treeOut())
      parseTree(headKey,\treeIn(),\treeOut(),pBar)
    EndWith
    
  EndProcedure
  
  Procedure showTreeView(*TreeView.treeView)
    
;     Shared treeViewMap.treeParams()
    ClearGadgetItems(*TreeView\wdgId)
    counter.i=-1
    With *TreeView
      ResetList(\treeOut())
      NextElement(\treeOut())
      Repeat
        counter=counter+1
        key=\treeOut()\wdgId
        text.s=\treeOut()\Text
        subLevel=\treeOut()\subLevel
        AddGadgetItem(*TreeView\wdgId,\treeOut()\wdgId,\treeOut()\Text,\treeOut()\ImageId,\treeOut()\subLevel)    
        NextElement(\treeOut())
      Until ListIndex(\treeOut()) = Counter

    EndWith
;     FreeStructure(*TreeView)
  EndProcedure
  
EndModule


;============================================= Modul Panel ==========================================================

DeclareModule Panel
  
  UseModule Container
  
  Structure Tab
    Map Wdg.widget()
    TabIndex.i
    TabText.s
  EndStructure
  
  Structure Panel ;Extends widget
    Map Tabs.Tab()   
    Name.s
    wdgId.i
    RefStrukt.i
    TabsCount.i
    StartX.i                           
    StartY.i                           
    StartW.i                           
    StartH.i                          
    Text.s                                   ; 
    Type.i
    ParentId.i
    RefParentStrukt.i
    isContainer.i
    ParentWin.i
    tempId.s
  EndStructure
  
   workTab.i
  Declare createPanel(x,y,w,h,TabCount.i=0)
  Declare removeTab(wdgId,TabItem)
  Declare setTabText(wdgId,TabIndex,Text.s)
  Declare removeAllTabs(wdgId)
  Declare setTab(ZielTab.i)
  Declare addTab(newWidgetFunktion.i,setTab.i)
  Declare createTab(PanelAdress.i,tabIndex.i)
;   Declare makeWidget(Map Wdg.widget(),wdgTyp)
  
EndDeclareModule

Module Panel
  

  UseModule TreeByKey

  
  Procedure setTab(IndexZielTab.i)
    Shared workTab
    workTab = IndexZielTab
    ProcedureReturn IndexZielTab
  EndProcedure
  
  
  Procedure createPanel(x,y,w,h,TabCount.i=0)
    
    wdgId = PanelGadget(#PB_Any, x, y, w, h)
    If TabCount > 0
      For i = 0 To TabCount-1
        AddGadgetItem(wdgId,i,"Tab " + Str(i))
      Next
    EndIf 
    
    ProcedureReturn wdgId
    
  EndProcedure  
  
  
  Procedure removeTab(wdgId,TabItem)
    
    If TabItem < CountGadgetItems(wdgId) : RemoveGadgetItem(wdgId,TabItem) : EndIf
    
  EndProcedure
  
  Procedure setTabText(wdgId,TabIndex,Text.s)
    
    SetGadgetItemText(wdgId,TabIndex,Text)
    
  EndProcedure
  
  Procedure removeAllTabs(wdgId)
    
    ClearGadgetItems(wdgId)
    
  EndProcedure
  
  Procedure addTab(newWidgetFunktion.i,setTab.i)
    ;dummy, Kreiert das Widget und merkt sich den Tab in Class-Variable
    
  EndProcedure
  


  Procedure makeWidget(Map WdgMap.widget(),wdgTyp)

     With WdgMap()
       Select wdgTyp
          
        Case #PB_GadgetType_Button
          wdgId = ButtonGadget(#PB_Any, \x, \y, \w, \h, \Text,\flag1 | \flag2 | \flag3| \flag4 | \flag5 | \flag6)

        Case #PB_GadgetType_Container
          wdgId = ContainerGadget(#PB_Any, \x, \y, \w, \h, \flag1 | \flag2 | \flag3| \flag4 | \flag5 | \flag6)

        Case #PB_GadgetType_Panel
          wdgId = createPanel(\x, \y, \w, \h,\TabCount)

        Case #PB_GadgetType_ScrollArea
          wdgId = ScrollAreaGadget(#PB_Any, \x, \y, \w, \h, \ScrollW, \ScrollH,\ScrollStep,\flag1 | \flag2 | \flag3| \flag4 | \flag5 | \flag6)

        Case #PB_GadgetType_String
          wdgId = StringGadget(#PB_Any, \x, \y, \w, \h, \Text,\flag1 | \flag2 | \flag3| \flag4 | \flag5 | \flag6)

        Case #GadgetType_TreeView
          wdgId = TreeByKey::createTreeByKey(\x,\y,\w,\h,\flag1,\flag2,\flag3,\flag4,\flag5,\flag6)
        Case #PB_GadgetType_Web
          wdgId = WebGadget(#PB_Any, \x, \y, \w, \h, \Url)
  ;       Case #PB_Type_Window
  ;         wdgId = OpenWindow(#PB_Any, x, y, w, h, Text,flag1 | flag2 | flag3| flag4 | flag5 | flag6)
      EndSelect
    EndWith
    ProcedureReturn wdgId
  EndProcedure
  
  Procedure createTab(*Panel.Panel,tabIndex.i)
    ClearGadgetItems(*Panel\wdgId)
    OpenGadgetList(*Panel\wdgId)
    
    For i=0 To *Panel\TabsCount
      With *Panel\Tabs(Str(i))
      AddGadgetItem(*Panel\wdgId,i,\TabText)
        ForEach \Wdg()
          \Wdg()\wdgId = makeWidget(\Wdg(),\Wdg()\Type)
          Delay(0.002)
        Next
      EndWith
    Next
    CloseGadgetList()
  EndProcedure
  
EndModule

;======================================================================================================
;======================================= ModWdgClass ==================================================
DeclareModule wdgClass
Enumeration 1717171717 Step 17                    ;Parameter: 
  #PB_ContainerType_Window  
  #PB_ContainerType_Container
  #PB_ContainerType_ScrollArea
  #PB_ContainerType_Canvas  

EndEnumeration

UseModule Panel
UseModule Container
UseModule TreeByKey


NewMap WdgMap.widget()
Global NewMap winMap.Container()

Declare New_Window(Name.s,x,y,w,h,Text.s,flag1 = #False,flag2 = #False,flag3 = #False,flag4 = #False,flag5 = #False,flag6 = #False)
Declare New_Button(ParentId,Name.s,x,y,w,h,Text.s,flag1 = #False,flag2 = #False,flag3 = #False,flag4 = #False,flag5 = #False,flag6 = #False)
Declare New_Container(ParentId,Name.s,x,y,w,h,flag1 = #False,flag2 = #False,flag3 = #False,flag4 = #False,flag5 = #False,flag6 = #False)
Declare New_Panel(ParentId,Name.s,x,y,w,h,TabCount=0)
Declare New_ScrollArea(ParentId,Name.s,x,y,w,h,ScrollW, ScrollH,ScrollStep=1,flag1 = #False,flag2 = #False,flag3 = #False,flag4 = #False,flag5 = #False,flag6 = #False)
Declare New_String(ParentId,Name.s,x,y,w,h,Text.s,flag1 = #False,flag2 = #False,flag3 = #False,flag4 = #False,flag5 = #False,flag6 = #False)
Declare New_TreeByKey(ParentId,Name.s,x,y,w,h,flag1 = #False,flag2 = #False,flag3 = #False,flag4 = #False,flag5 = #False,flag6 = #False)
;-------------------------------
Declare GetWdgRefStrukt(wdgId.i)
Declare wdgOnFly(Map WdgMap.widget(),wdgTyp)
EndDeclareModule

Module wdgClass
  Procedure parseStruktName(*workStrukt.Container,Name.s="") ;sucht in Window oder Container nach StrukturReferenz zu GadgetId
    ;UseModule Container
  
;     With *workStrukt
      If MapSize(*workStrukt\childMap()) > 0
        ForEach *workStrukt\childMap()
          If *workStrukt\childMap()\Name=Name 
            ProcedureReturn #True : Break
          EndIf
          If *workStrukt\childMap()\isContainer
;             Debug *workStrukt
            If parseStruktName(*workStrukt\childMap()\RefStrukt,Name) = #True
              ProcedureReturn #True: Break
            EndIf
          EndIf
        Next
      EndIf
;     EndWith
  
  EndProcedure
  
  Procedure GetWdgName(Name.s)
    UseModule Container
    Shared winMap()
    ForEach winMap()
      *winContainer.Container = AllocateStructure(Container)
      adressWinCon.i = *winContainer
      Debug *winContainer
      AddMapElement(*winContainer\childMap(),MapKey(winMap()))
      If MapSize(winMap(MapKey(winMap()))\childMap())>0 
        *winContainer=winMap(MapKey(winMap())) 
      EndIf
      If parseStruktName(*winContainer,Name) 
        Debug *winContainer
        FreeStructure(adressWinCon)
        ProcedureReturn #True 
        Break  
      EndIf
;             If parseStruktName(@winMap(MapKey(winMap())),Name) : ProcedureReturn #True : Break : EndIf
    Next
    ProcedureReturn #False
  EndProcedure
  
  Procedure checkName(Name.s)
    
    If GetWdgName(Name) = #True 
      MessageRequester("Warnung!","Das Widget " + Chr(34)  + Name + Chr(34) + " ist bereits vorhanden.") 
      ProcedureReturn #True
    EndIf
    
  EndProcedure
  
  Procedure parseStruktId(wdgId.i,*workStrukt.Container) ;sucht in Window oder Container nach StrukturReferenz zu GadgetId
    ;UseModule Container
  
    With *workStrukt
      If MapSize(\childMap()) > 0
        If \childMap(Str(wdgId))\RefStrukt
          ProcedureReturn \childMap(Str(wdgId))\RefStrukt
        Else
          ForEach \childMap()
            If \childMap()\isContainer
              wdgStrukt = parseStruktId(wdgId.i,*workStrukt\childMap()\RefStrukt)
              If wdgStrukt > 0 : ProcedureReturn wdgStrukt : EndIf  
              Break
            EndIf
          Next
        EndIf
      EndIf 
    EndWith
    
  EndProcedure
  
  Procedure GetWdgRefStrukt(wdgId.i)
    
    Shared winMap()
    ForEach winMap()
      wdgStrukt = parseStruktId(wdgId,@winMap(MapKey(winMap())))
      If wdgStrukt > 0 
        ProcedureReturn wdgStrukt
      EndIf 
    Next
    
  EndProcedure
  
  Procedure getConWindow(ParentConId.i)
    ;UseModule Container
    ende.i = #False
    Repeat
      *Parent.Container = GetGadgetData(ParentConId)
      If IsWindow(*Parent\ParentId)
        ende=#True : ProcedureReturn *Parent\ParentId
      Else 
        ende=#True : getConWindow(*Parent\ParentId)
      EndIf 
    Until ende = #True
  EndProcedure
  
  Procedure InWdgMapEintragen(Map WdgMap.widget(),ParentId,Name.s,Type.i,x,y,w,h,flag1 = #False,flag2 = #False,
                              flag3 = #False,flag4 = #False,flag5 = #False,flag6 = #False)
    
    ClearMap(WdgMap())
    AddMapElement(WdgMap(), Name)
    With WdgMap()
      \x=x : \y=y : \w=w : \h=h : \flag1=flag1 : \flag2=flag2  : \Name=Name
      \flag3=flag3 : \flag4=flag4 : \flag5=flag5 : \flag6=flag6 : \ParentId=ParentId : \Type=Type
    EndWith
    
  EndProcedure
  
  Procedure InWinMapEintragen(Map WdgMap.widget())
    
    Shared WinMap()
    AddMapElement(winMap(Str(WdgMap()\ParentId))\childMap(),Str(WdgMap()\wdgId))
    With winMap()\childMap()
      \StartX=WdgMap()\x : \StartY=WdgMap()\y : \StartW=WdgMap()\w : \StartH=WdgMap()\h : \Name = WdgMap()\Name 
      \ParentId = WdgMap()\ParentId : \wdgId = WdgMap()\wdgId : \RefStrukt = WdgMap()\RefStrukt
      \isContainer=WdgMap()\isContainer : \ParentWin = WdgMap()\ParentWin
    EndWith
    
  EndProcedure
  
  Procedure InPanelMapEintragen(Map WdgMap.widget())
    ;UseModule Panel
    dummyId = Random(10000,1000)
    WdgMap()\wdgId = dummyId
    *Panel.Panel = GetWdgRefStrukt(WdgMap()\ParentId)
  
    *Panel\tempId = Str(dummyId)
    If panel::workTab > *Panel\TabsCount : *Panel\TabsCount = Panel::workTab : EndIf
    If FindMapElement(*Panel\Tabs(),Str(panel::workTab)) = #False
      AddMapElement(*Panel\Tabs(),Str(Panel::workTab))
    EndIf
    AddMapElement(*Panel\Tabs(Str(Panel::workTab))\Wdg(),Str(dummyId))
    *Panel\Tabs(Str(Panel::workTab))\TabIndex = panel::workTab
    *Panel\Tabs(Str(Panel::workTab))\Wdg(Str(dummyId)) = WdgMap()
  
    ProcedureReturn *Panel
    
  EndProcedure
  
  Procedure InConMapEintragen(Map WdgMap.widget())
    
    ;UseModule Container
    *Parent.Container = GetWdgRefStrukt(WdgMap()\ParentId) ;getParentContainer(ParentId)
    AddMapElement(*Parent\childMap(),Str(WdgMap()\wdgId))
    With *Parent\childMap(Str(WdgMap()\wdgId))
      \StartX=WdgMap()\x : \StartY=WdgMap()\y : \StartW=WdgMap()\w : \StartH=WdgMap()\h : \Name = WdgMap()\Name 
      \ParentId = WdgMap()\ParentId : \wdgId = WdgMap()\wdgId : \RefStrukt = WdgMap()\RefStrukt
      \isContainer=WdgMap()\isContainer : \ParentWin = WdgMap()\ParentWin
    EndWith
    
  EndProcedure
  
  Procedure allocContainerWriteStructur(Map WdgMap.widget())
    
    ;UseModule Container
    With WdgMap()
      Select \Type
        Case #PB_GadgetType_Container,#PB_GadgetType_ScrollArea
          CloseGadgetList()
          *Container.Container = AllocateStructure(Container)
          \RefStrukt = *Container : \isContainer = #True
          *Container\wdgId= \wdgId : *Container\RefStrukt= *Container :*Container\ParentId = \ParentId :*Container\StartX = \x
          *Container\StartY = \y : *Container\StartW = \w : *Container\StartH = \h : *Container\isContainer = #True
          If IsWindow(\ParentId) : *Container\ParentWin = \ParentId :Else: *Container\ParentWin = getConWindow(\ParentId):EndIf
          SetGadgetData(\wdgId ,*Container)
        Case #PB_GadgetType_Panel
          CloseGadgetList() ;neue PanelGadgetList muss geschlossen werden, da ansonsten alle weiteren Gadgets darin platziert würden.
          *Panel.Panel = AllocateStructure(Panel)
          \RefStrukt = *Panel : \isContainer = #True
          *Panel\wdgId=\wdgId : *Panel\RefStrukt = *Panel : *Panel\ParentId = \ParentId : *Panel\StartX = \x 
          *Panel\StartY = \y : *Panel\StartW = \w : *Panel\StartH = \h : *Panel\Name = \Name
          If IsWindow(\ParentId) : *Panel\ParentWin = \ParentId : Else: *Panel\ParentWin = getConWindow(\ParentId):EndIf
        Case #GadgetType_TreeView
          *treeView.treeView = AllocateStructure(treeView)
          \RefStrukt = *treeView
          *treeView\wdgId=\wdgId : *treeView\RefStrukt = *TreeView : *treeView\ParentId = \ParentId : *treeView\StartX = \x 
          *treeView\StartY = \y : *treeView\StartW = \w : *treeView\StartH = \h : *treeView\Name = \Name
          If IsWindow(\ParentId) : *TreeView\ParentWin = \ParentId : Else: *TreeView\ParentWin = getConWindow(\ParentId):EndIf

      EndSelect  
    EndWith
  EndProcedure
     
  Procedure WdgHandler(Map WdgMap.widget())
    
    If checkName(WdgMap()\Name) : ProcedureReturn : EndIf
    With WdgMap()
      If IsWindow(\ParentId)
        UseGadgetList(WindowID(\ParentId))
        \wdgId = wdgOnFly(WdgMap(),\Type)
        allocContainerWriteStructur(WdgMap())
        InWinMapEintragen(WdgMap())
      ElseIf GadgetType(\ParentId) <> #PB_GadgetType_Panel
        OpenGadgetList(\ParentId)
          \wdgId = wdgOnFly(WdgMap(),\Type)
        CloseGadgetList()
        allocContainerWriteStructur(WdgMap())
        InConMapEintragen(WdgMap())
      ElseIf  GadgetType(\ParentId)=#PB_GadgetType_Panel
        *Panel.Panel = InPanelMapEintragen(WdgMap())
        Panel::createTab(*Panel,panel::workTab) : ProcedureReturn
      EndIf
    EndWith
    
  EndProcedure

  Procedure wdgOnFly(Map WdgMap.widget(),wdgTyp)

     With WdgMap()
     Select wdgTyp
        
      Case #PB_GadgetType_Button
        wdgId = ButtonGadget(#PB_Any, \x, \y, \w, \h, \Text,\flag1 | \flag2 | \flag3| \flag4 | \flag5 | \flag6)
      Case #PB_GadgetType_Container
        wdgId = ContainerGadget(#PB_Any, \x, \y, \w, \h, \flag1 | \flag2 | \flag3| \flag4 | \flag5 | \flag6)

      Case #PB_GadgetType_Panel
        wdgId = createPanel(\x, \y, \w, \h,\TabCount)
      Case #PB_GadgetType_ScrollArea
        wdgId = ScrollAreaGadget(#PB_Any, \x, \y, \w, \h, \ScrollW, \ScrollH,\ScrollStep,\flag1 | \flag2 | \flag3| \flag4 | \flag5 | \flag6)

      Case #PB_GadgetType_String
        wdgId = StringGadget(#PB_Any, \x, \y, \w, \h, \Text,\flag1 | \flag2 | \flag3| \flag4 | \flag5 | \flag6)

      Case #GadgetType_TreeView
        wdgId = TreeByKey::createTreeByKey(\x,\y,\w,\h,\flag1,\flag2,\flag3,\flag4,\flag5,\flag6)

    EndSelect
   EndWith
   ProcedureReturn wdgId
  EndProcedure

  Procedure New_Window(Name.s,x,y,w,h,Text.s,flag1 = #False,flag2 = #False,flag3 = #False,flag4 = #False,flag5 = #False,flag6 = #False)
    
    Shared WinMap()
    
    wdgId = OpenWindow(#PB_Any, x, y, w, h, Text,flag1 | flag2 | flag3| flag4 | flag5 | flag6)
    AddMapElement(winMap(),Str(wdgId))
    With winMap()
      \StartX=x : \StartY=y : \StartW=w : \StartH=h : \Text = Text : \Type = #PB_ContainerType_Window : \Name = Name : \wdgId = wdgId
    EndWith
    ProcedureReturn wdgId
    
  EndProcedure
  
  Procedure New_Button(ParentId,Name.s,x,y,w,h,Text.s,flag1 = #False,flag2 = #False,flag3 = #False,flag4 = #False,flag5 = #False,flag6 = #False)
    
    Shared WdgMap()
    InWdgMapEintragen(WdgMap(),ParentId, Name, #PB_GadgetType_Button, x,y,w,h,flag1,flag2,flag3,flag4,flag5,flag6)
    WdgMap()\Text=Text
    WdgHandler(WdgMap()) : ProcedureReturn WdgMap()\wdgId
    
  EndProcedure
  
  
  Procedure New_Container(ParentId,Name.s,x,y,w,h,flag1 = #False,flag2 = #False,flag3 = #False,flag4 = #False,flag5 = #False,flag6 = #False)
    
    Shared WdgMap()
    InWdgMapEintragen(WdgMap(),ParentId, Name, #PB_GadgetType_Container, x,y,w,h,flag1,flag2,flag3,flag4,flag5,flag6)
    WdgHandler(WdgMap()) : ProcedureReturn WdgMap()\wdgId
    
  EndProcedure
  
  
  Procedure New_Panel(ParentId,Name.s,x,y,w,h,TabCount=0)
    
    Shared WdgMap()
    InWdgMapEintragen(WdgMap(),ParentId, Name, #PB_GadgetType_Panel, x,y,w,h,flag1,flag2,flag3,flag4,flag5,flag6)
    WdgMap()\TabCount = TabCount
    WdgHandler(WdgMap()) : ProcedureReturn WdgMap()\wdgId
    
  EndProcedure
  
  
  Procedure New_ScrollArea(ParentId,Name.s,x,y,w,h,ScrollW, ScrollH,ScrollStep=1,flag1 = #False,flag2 = #False,flag3 = #False,flag4 = #False,flag5 = #False,flag6 = #False)
    
    Shared WdgMap()
    InWdgMapEintragen(WdgMap(),ParentId, Name, #PB_GadgetType_ScrollArea, x,y,w,h,flag1,flag2,flag3,flag4,flag5,flag6)
    WdgMap()\ScrollW = scrollW : WdgMap()\ScrollH = scrollH : WdgMap()\ScrollStep = ScrollStep
    WdgHandler(WdgMap()) : ProcedureReturn WdgMap()\wdgId
    
  EndProcedure
  
  
  Procedure New_String(ParentId,Name.s,x,y,w,h,Text.s,flag1 = #False,flag2 = #False,flag3 = #False,flag4 = #False,flag5 = #False,flag6 = #False)
    
    Shared WdgMap()
    InWdgMapEintragen(WdgMap(),ParentId, Name, #PB_GadgetType_String, x,y,w,h,flag1,flag2,flag3,flag4,flag5,flag6)
    WdgMap()\Text = Text
    WdgHandler(WdgMap()) : ProcedureReturn WdgMap()\wdgId
    
  EndProcedure
  

  
  Procedure New_TreeByKey(ParentId,Name.s,x,y,w,h,flag1 = #False,flag2 = #False,flag3 = #False,flag4 = #False,flag5 = #False,flag6 = #False)
    
    Shared WdgMap()
    InWdgMapEintragen(WdgMap(),ParentId, Name, #GadgetType_TreeView, x,y,w,h,flag1,flag2,flag3,flag4,flag5,flag6)
    WdgHandler(WdgMap()) : ProcedureReturn WdgMap()\wdgId
    
  EndProcedure
  

EndModule

;=============================================================================================================
;================================================= myWindow ==================================================
Global  app_Name.s = "dbAdmin",ini$ = app_Name + ".setting",Dim mysp.s(0),activeGadget.i
Global dbName.s,mainWin,dbTreeView
UseModule wdgClass

UseModule Panel
UseModule TreeByKey

Enumeration fenster
  #mainWin
  #_Type_menu
  #_unvis_menu
;   #MenuEvent_ReturnKey
EndEnumeration



Procedure DoEventReturnKey()
  PostEvent(#PB_Event_Gadget, GetActiveWindow(), GetActiveGadget(), #PB_EventType_ReturnKey)
EndProcedure

Procedure windowOpen()

  mainWin=New_Window("mainWin",0,0,500,300,"dbAdmin",#PB_Window_SystemMenu)
  Container1 = New_ScrollArea(mainWin,"Container1",10, 55, 400, 190,500,200,#PB_ScrollArea_Flat)
  Container2 = New_Container(Container1,"Container2",15,15,350,150,#PB_Container_Single )
  Container3 = New_Container(Container2,"Container3",15,15,300,120,#PB_Container_Single )
  Container4 = New_Container(Container3,"Container4",15,15,270,100,#PB_Container_Single )
  Container5 = New_ScrollArea(Container4,"Container5",15, 15, 250, 80,500,200,#PB_ScrollArea_Flat)
  Button_2=New_Button(Container1,"Button_2",10,10,80,30,"Bu 1")
  inContainer1 = New_Panel(Container1,"inContainer1",200, 40, 300, 150,2)
  UseModule panel
  Button_5 = panel::addTab(New_Button(inContainer1,"Button_5",5,5,80,30,"Button_5"),setTab(0))
  Button_6 = panel::addTab(New_Button(inContainer1,"Button_6",85,5,80,30,"Button_6"),setTab(0))
  Button_7 = panel::addTab(New_Button(inContainer1,"Button_7",5,5,80,30,"Button_7"),setTab(1))

  Text_10 = panel::addTab(New_string(inContainer1,"Text_10",5,40,80,30,"Hallo"),setTab(0))
  dbTreeView2=panel::addTab(New_TreeByKey(inContainer1,"dbTreeView2",5,50,150,100),setTab(1))

  Button_3=New_Button(Container1,"Button_3",10,10,80,30,"inBu")
  Button_4=New_Button(Container1,"Button_3",10,10,80,30,"inBu2")


EndProcedure

;=========================================================================================================
;======================================== Main ===========================================================

UseModule wdgClass

windowOpen()


Repeat
myEvent=WaitWindowEvent()
   
Until myEvent = #PB_Event_CloseWindow ; Beenden, wenn eines der Fenster geschlossen wird.

;=======================================================================================================
Benutzeravatar
helpy
Beiträge: 635
Registriert: 29.08.2004 13:29

Re: Verständnisfrage zu Strukturen

Beitrag von helpy »

Ich weiß zwar nicht, ob Punkt 1 zur Lösung beiträgt, aber folgender Code ist nicht sehr sinnvoll:

Code: Alles auswählen

 ... winMap(MapKey(winMap())) ...
Das ist meines Wissens identisch mit:

Code: Alles auswählen

 ... winMap() ...
winMap() bezieht sich auf das aktuell aktive Element! MapKey(winMap()) ruft den key des aktuellen Elements ab. Mit dem so ermittelten key dann das aktuelle Element abzurufen (erster Code) ist redundant und verbraucht unnötig Rechenzeit!

Punkt 2: Der Fehler liegt eher in einem Logikfehler in der Procedure parseStruktName!
Als erstes Element erwartet parseStruktName eine Struktur vom Typ Container.
Im rekursiven Aufruf innerhalb von parseStruktName steht aber folgendes:

Code: Alles auswählen

If parseStruktName(*workStrukt\childMap()\RefStrukt,Name) = #True

*workStrukt\childMap()\RefStrukt kann ABER ja nach Fall ein Pointer auf ein Struktur-Element vom Typ Container, Panel oder treeView sein. Hier kann es bereits zu vielerlei Falschzuweisungen kommen, weil alle drei Strukturen sich voneinander unterscheiden!
Dass es hier zu Fehlern kommt, ist schon vorprogrammiert ;-)

Punkt 3: Ein weiterer Logikfehler in der Procedure parseStruktName:
Es geht um folgende Abfrage:

Code: Alles auswählen

If \childMap(Str(wdgId))\RefStrukt
Hierzu musst Du wissen dass mapName(mapKey) immer ein neues Map-Element anlegt, wenn unter dem key mapKey noch kein Element existiert!
Wenn das Map-Element Str(wdgId) nicht in \childMap() existiert, wird bei dieser Abfrage in neues Element mit dem Key Str(wdgId) angelegt. In meinem Testlauf, war dies der Fall!
Willst Du das wirklich?
Wenn nicht, dann musst Du vorher mit FindMapElement(\childMap(),Str(wdgId)) prüfen, ob ein Element mit den Key Str(wdgId) überhaupt existiert, bevor Du mit \childMap(Str(wdgId)) auf das Element zugreifst.

Punkt 4: Verwende in jedem Fall EnableExplicit und deklariere alle Variablen zuvor!
Damit EnableExplicit überall greift, muss am Anfang im globalen Scope und am Anfang von jedem DeclareModule stehen.

Und noch mehr ...
  • Ich persönlich meide Shared grundsätzlich.
  • Sollen Variablen in einer Procedure im rekursiven Aufruf unverändert sein, dann verwende lieber Static Variablen!
  • Ergänzung zu Punkt 2: Wenn Du möchtest, dass bestimmte Strukturen im ersten Teil identisch (Container, Panel, treeView) sind, dann lege eine Basis-Struktur an von der die anderen Erben (Structure A Extends BaseStructure)

Ich hoffe, dass der eine oder andere Hinweis, dir etwas weiterhilft.
Gruß aus Niederbayern ...
Windows 10
PB Last Final / (Sometimes testing Beta versions)
kmais
Beiträge: 45
Registriert: 09.02.2017 13:54

Re: Verständnisfrage zu Strukturen

Beitrag von kmais »

Danke, helpy ... :-), das war konstruktiv :allright:

Zum Punkt 1.
das soll so sein, da hier evtl. noch mehrere Fenster verwalten werden sollen. Daher der Zugriff über die MapId (mapkey()).

Das Problem liegt wirklich an den unterschiedlichen Strukturen. Ich habe mir das mal genau, auch im Speicher, angeschaut.
Die Panelstruktur hatte einen Eintrag mehr. Der Compiler kontrolliert wohl leider die Strukturtypen nicht. Das wäre hier hilfreich
gewesen wenn der eine Warnung ausgegeben hätte.
Liegen alle Elemente der Struktur ÜBER dem letzten Eintrag läuft es. Liegt einer davon unter dem letzten (unterschiedlichen) Eintrag
hängt er. Die Struktur wird wohl von oben über den Stack abgearbeitet und wenn dann ein Element unterhalb liegt weiß er sich keinen
Rat mehr :-).

Deinen Hinweis auf die Rekursion muss ich mir jetzt mal genau anschauen :bluescreen:

Vielen, vielen Dank nach Niederbayern und Grüße aus dem Saarland ....
Benutzeravatar
helpy
Beiträge: 635
Registriert: 29.08.2004 13:29

Re: Verständnisfrage zu Strukturen

Beitrag von helpy »

kmais hat geschrieben:Zum Punkt 1.
das soll so sein, da hier evtl. noch mehrere Fenster verwalten werden sollen. Daher der Zugriff über die MapId (mapkey()).
Sorry. Das widerspricht meinem Verständnis der Funktion von Maps und der Verwendung von MapKey().
Der Code ...

Code: Alles auswählen

winMap(MapKey(winMap()))
... ist eindeutig redundanter Code, den Du getrost durch ...

Code: Alles auswählen

winMap()
... ersetzen kannst!

Wenn Du durch den Key das Fenster auswählen willst, dann braucht es einen Key für das Fenster:

Code: Alles auswählen

winMap(FensterKey)
Aber vielleicht habe ich ja Scheuklappen auf.
Evt. kann da einer der PB-Experten etwas dazu sagen.

Viele Grüße,
Guido
Windows 10
PB Last Final / (Sometimes testing Beta versions)
Nino
Beiträge: 1300
Registriert: 13.05.2010 09:26
Wohnort: Berlin

Re: Verständnisfrage zu Strukturen

Beitrag von Nino »

helpy hat geschrieben:Aber vielleicht habe ich ja Scheuklappen auf.
Nein, Du hast vollkommen recht. Der betr. Code ist unsinnig, ebenso wie etwa

Code: Alles auswählen

x = a + 2 - 2
o. Ä.
Antworten