Objekt-Informationen rekursiv Aufruf

Stelle Fragen zur Programmierung mit Autohotkey

Moderator: jNizM

User avatar
Gerdi
Posts: 185
Joined: 03 Aug 2015, 18:48
Location: Germany
Contact:

Objekt-Informationen rekursiv Aufruf

02 Nov 2017, 19:43

Beim Versuch Objekte besser zu verstehen habe ich untenstehende Funktion erstellt.

Code: Select all

GetObjectDetails(obj,Tiefe="")
{
	if (not IsObject(obj))
		return obj
	if (StrLen(Tiefe)>25)
		return
	DieseTiefe:=Tiefe
	Tiefe.=A_Tab
	try
	{
		For KeyName, KeyValue in obj
		{
			ValDetails:=
			Details:=
			if (IsObject(KeyValue))
				Details:=GetObjectDetails(KeyValue,Tiefe)
			else
				ValDetails:=KeyValue
			Text.=DieseTiefe KeyName "	" ValDetails "`n" Details
		}
	}
	return Text
}
Aufruf nur mit einem Objekt ohne den 2. Parameter, der wird fuer den rekursiven Aufruf benoetigt.
Nun zu meiner Frage: Die Funktion liefert zwar brauchbare Ergebnisse, aber hat der rekursive Eigen-Aufruf Risiken und Nebenwirkungen?
Win 10 Home (x64) and Win 11 Pro N
https://github.com/Grrdi/ZackZackOrdner/archive/master.zip --> get folders on the quick
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Objekt-Informationen rekursiv Aufruf

02 Nov 2017, 21:33

Ja den hat es. Vor allem dann wenn du mit Zirkulären Referenzen arbeitest:

Code: Select all

a := []
b := [a]
a.1 := b
Msgbox % GetObjectDetails( a )


GetObjectDetails(obj,Tiefe="")
{
	if (not IsObject(obj))
		return obj
	if (StrLen(Tiefe)>25)
		return
	DieseTiefe:=Tiefe
	Tiefe.=A_Tab
	try
	{
		For KeyName, KeyValue in obj
		{
			ValDetails:=
			Details:=
			if (IsObject(KeyValue))
				Details:=GetObjectDetails(KeyValue,Tiefe)
			else
				ValDetails:=KeyValue
			Text.=DieseTiefe KeyName "	" ValDetails "`n" Details
		}
	}
	return Text
}
Jedoch umgehst du diese bereits mit StrLen( Tiefe ) > 25.
Allgemein ist es so, dass es viele Versionen dieser speziellen Funktion gibt - jeder hat da seine eigenen Vorlieben - jedoch sehe ich, bei den meisten, dass Rekursion verwendet wird.
Recommends AHK Studio
User avatar
Gerdi
Posts: 185
Joined: 03 Aug 2015, 18:48
Location: Germany
Contact:

Re: Objekt-Informationen rekursiv Aufruf

03 Nov 2017, 06:39

Danke nnnik.

Ich wuensche mir eine Version mit dieser Grundfunktionalitaet in der AHK-Hilfe.
Vielleicht liest ja ein Entscheidungstraeger mit.
Last edited by Gerdi on 03 Nov 2017, 16:41, edited 1 time in total.
Win 10 Home (x64) and Win 11 Pro N
https://github.com/Grrdi/ZackZackOrdner/archive/master.zip --> get folders on the quick
User avatar
Gerdi
Posts: 185
Joined: 03 Aug 2015, 18:48
Location: Germany
Contact:

Re: Objekt-Informationen rekursiv Aufruf

03 Nov 2017, 16:31

Gib es einen vernuenftigen Einsatzfall, bei dem zirkulaere Referenzen sinn machen? Oder ist da im Model der Wirklichkeitsabbildung schon ein (Denk-)Fehler?
Win 10 Home (x64) and Win 11 Pro N
https://github.com/Grrdi/ZackZackOrdner/archive/master.zip --> get folders on the quick
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Objekt-Informationen rekursiv Aufruf

04 Nov 2017, 08:13

Jegliche Objekt Relation ist eigentlich immer beidseitig:
Ein Besitzer besitzt Besitz und Besitz wird von einem Besitzer besessen.
Ein Spielstein befindet sich in einem Spielfeld ein Spielfeld enthält einen Spielstein...
Usw...
Da Zirkuläre Referenzen in der Programmierungs Praxis Probleme machen gibt es verschiedene Techniken sie zu umgehen:
  1. Man bildet einen Teil der Wirklichkeit nicht ab
    Muss jetzt Besitz speichern von wem es besessen wird oder nicht und wenn ja muss ein Besitzer wissen was er Besitzt?
  2. Man geht einen Umweg über ein Super-Globales Objekt:
    z. B. man speichert welche Farbe ein Spielstein hat und legt in ein superglobales Array den Spieler der entsprechenden Farbe ab und greift dann auf den entsprechenden Index auf das Objekt zu.
    Spieler := { Schwarz:SpielerA, Weiß:SpielerB }
  3. Man verwendet einen schwachen Verweis:
    Es gibt hier sehr viele Möglichkeiten mit Objekt Pointern zu arbeiten:

    Code: Select all

    besitz := []
    besitzer := [besitz]
    besitz.1 := &besitz ;den objekt pointer speichern
    Msgbox % besitzer == Object( besitz.1 )
Wenn nichts von all dem hilft kann man natürlich auch einfach versuchen die Probleme, die Zirkuläre Referenzen verursachen zu umgehen.
Recommends AHK Studio
User avatar
Gerdi
Posts: 185
Joined: 03 Aug 2015, 18:48
Location: Germany
Contact:

Re: Objekt-Informationen rekursiv Aufruf

05 Nov 2017, 04:50

Vielen Dank nnnik,

ich habe versucht Dein 3. Beispiel mit Besitz zu fuellen:

Code: Select all

GetObjectDetails_KKA:="["
GetObjectDetails_KKZ:="]"
GetObjectDetails_VKA:="["""
GetObjectDetails_VKZ:="""]"
besitz := []
besitzer := [besitz]
besitz.Pointer := &besitz ;den objekt pointer speichern
Msgbox % besitzer == Object( besitz.Pointer  ) 
MsgBox %  GetDetailesOfOjects(besitz,"besitz",besitzer,"besitzer")
besitz.push("Auto")
besitz.push("Haus")
MsgBox %  GetDetailesOfOjects(besitz,"besitz",besitzer,"besitzer")
ExitApp
GetDetailesOfOjects(Objects*)			; GetDetailesOfOjects(Obj1,Obj1Name , Obj2,Obj2Name , ...)	
{
	global GetObjectDetails_Zirkel
	for index,Obj in Objects
	{
		if (mod(index,2))			; ungerade
		{
			LastObj:=Obj
		}
		else
		{
			GetObjectDetails_Zirkel:=false

			; ObjName:=Obj
			DetailesOfOjects.=GetObjectDetails(LastObj,Obj) "`n"
			if GetObjectDetails_Zirkel
				DetailesOfOjects.=Obj " hat vermutlich eine Zirkulaere Referenz!`n"
		}
	}
	DetailesOfOjects.="`n"
	return DetailesOfOjects
}
GetObjectDetails(obj,ObjName="",Tiefe="") ; vor dem Aufruf kann die globale Variable GetObjectDetails_Zirkel:=false gestzt werden. Ist diese nach dem Aufruf true, dan besteht wahrscheinlich ein Zirkelbezug in der Ojekterzeugung. 
{
/*	Vor dem Funktionsaufruf koennen diese Variabeln gesetzt werden. fuer die erste 4 reicht eimaliges setzen.
GetObjectDetails_KKA:="["
GetObjectDetails_KKZ:="]"
GetObjectDetails_VKA:="["""
GetObjectDetails_VKZ:="""]"
    fuer [Key]	["Value"]
GetObjectDetails_Zirkel:=false
*/
	Global GetObjectDetails_KKA, GetObjectDetails_KKZ, GetObjectDetails_VKA, GetObjectDetails_VKZ, GetObjectDetails_Zirkel
	if (not IsObject(obj))
	{
		if (StrLen(ObjName)>0)
			return ObjName "=	" obj
		else
			return obj
	}
	if (StrLen(Tiefe)>25)
	{
		GetObjectDetails_Zirkel:=true
		return
	}
	if (StrLen(ObjName)>0)
	{
		Text:=ObjName "=`n"
		ObjName:=""
		Tiefe.=A_Tab
	}
	DieseTiefe:=Tiefe
	Tiefe.=A_Tab
	try
	{
		For KeyName, KeyValue in obj
		{
			ValDetails:=
			Details:=
			if (IsObject(KeyValue))
				Details:=GetObjectDetails(KeyValue,ObjName,Tiefe)
			else
				ValDetails:=KeyValue
			if(ValDetails="")
				Text.=DieseTiefe GetObjectDetails_KKA KeyName GetObjectDetails_kKZ "`n"   Details 
			else
				Text.=DieseTiefe GetObjectDetails_KKA KeyName GetObjectDetails_kKZ "	" GetObjectDetails_VKA ValDetails GetObjectDetails_VKZ "`n"   Details 
		}
	}
	return Text
}
Habe allerdings noch Herausforderungen, inwiefern mich der schwache Verweis weitergebracht hat.
Ich kann von Dir allerdings nicht erwarten, dass Du mir noch laenger Nachhilfe gibst.

Wuerde mich trotzdem nicht gegen weiterfuehrende Links wehren.
Last edited by Gerdi on 05 Nov 2017, 05:01, edited 1 time in total.
Win 10 Home (x64) and Win 11 Pro N
https://github.com/Grrdi/ZackZackOrdner/archive/master.zip --> get folders on the quick
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Objekt-Informationen rekursiv Aufruf

05 Nov 2017, 04:59

Ich habe mal in cocos ( ich glaube es war coco ) Objekt display funktion gesehen wie er einen array an unterliegende rekursive funktionen abgegeben hat und die Pointer jedes Objekts als key weitergegeben hat um doppelnennungen zu vermeiden.
Ich denke das würde sich bei dir auch anbieten.
Recommends AHK Studio
User avatar
Gerdi
Posts: 185
Joined: 03 Aug 2015, 18:48
Location: Germany
Contact:

Re: Objekt-Informationen rekursiv Aufruf

05 Nov 2017, 06:08

Jetzt muss ich doch noch einmal nachhaken
um doppelnennungen zu vermeiden
Wo ist meine Doppelnennung?
Ist da ein Fehler in meiner Funktion GetObjectDetails?
Sie zeigt sinngemaess das gleiche an, wie Object Inspection im Debugger von Scite.
Win 10 Home (x64) and Win 11 Pro N
https://github.com/Grrdi/ZackZackOrdner/archive/master.zip --> get folders on the quick
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Objekt-Informationen rekursiv Aufruf

05 Nov 2017, 06:55

Moin,

ich bin kein OOP Experte. Alles, was ich über OOP/Objekte weiß, kommt ausschließlich vom Herumprobieren mit AHK-Objekten.

Zirkuläre Referenzen sind an sich kein Teufelskram. Sie haben nur zwei mir bekannte Nachteile:
  • Sie lassen sich nicht ohne Weiteres freigeben.
  • Sie verursachen Probleme in Funktionen, die die Objektstruktur ausgeben sollen.
Ich selbst habe sie bisher aber nicht genutzt, weil
  • ich bisher keinen Anwendungsfall hatte, in dem ich das brauchte.
  • ich (noch) glaube, dass es immer eine Alternative gibt.
Innerhalb von Funktionen wie GetObjectDetails() wird es dann kompliziert, wenn man innerhalb eines Zweiges eines Objekts ein Objekt findet, das auf ein früheres Element dieses Zweiges verweist. Das führt dann in eine Endlosschleife, wenn man es nicht abfängt. Ich habe schon vor längerer Zeit versucht, dieses Problem zu lösen. Ich habe dafür auch vorhandene Lösungen anderer User genutzt, finde die im Augenblick aber nicht mehr. Dabei wird innerhalb der Funktion ein statisches Objekt genutzt, in dem sämtliche referenzierten Objekte des Zweiges abgelegt werden. Wenn man auf ein Objekt stößt, kann so geprüft werden, ob das in diesem Zweig bereits vorher auftaucht. Ggf. wird es als 'zirkuläre Referenz' markiert und nicht weiter verarbeitet. Ich habe Deine ursprüngliche Funktion entsprechend angepasst und knapp getestet:

Code: Select all

GetObjectDetails(Obj, ObjektPfad := "RootObjekt", Tiefe := "")
{
   Static Objekte
   If !IsObject(Obj)
      Return Obj
   If (StrLen(Tiefe) > 25)
      Return
   If (Tiefe = "")
      Objekte := []
   If !Objekte.Haskey(&Obj)
      Objekte[&Obj] := ObjektPfad
   Text := ""
   Try
   {
      For KeyName, KeyValue In Obj
      {
         ValDetails := ""
         ObjDetails := ""
         If (IsObject(KeyValue))
            If Objekte.HasKey(&KeyValue)
            {
               Text .= Tiefe . KeyName . A_Tab . "-> " . Objekte[&KeyValue] . "`n"
               Continue
            }
            Else
            {
               ObjDetails := GetObjectDetails(KeyValue, ObjektPfad . "." . KeyName, Tiefe . A_Tab)
            }
         Else
         {
            ValDetails := KeyValue
         }
         Text .= Tiefe . KeyName . A_Tab . ValDetails . "`n" . ObjDetails
      }
   }
   Objekte.Delete(&Obj)
   Return Text
}
Last edited by just me on 06 Nov 2017, 04:29, edited 2 times in total.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Objekt-Informationen rekursiv Aufruf

05 Nov 2017, 07:20

Ja so meinte ich das ungefähr ( anstatt mit einer statischen Variable hätte ich einfach ein Objekt über einen Parameter an unterliegende Funktionen gegeben )
Recommends AHK Studio
User avatar
Gerdi
Posts: 185
Joined: 03 Aug 2015, 18:48
Location: Germany
Contact:

Re: Objekt-Informationen rekursiv Aufruf

06 Nov 2017, 01:44

:thumbup: Euch beiden ein ganz dickes Danke! :thumbup:
Win 10 Home (x64) and Win 11 Pro N
https://github.com/Grrdi/ZackZackOrdner/archive/master.zip --> get folders on the quick
User avatar
Gerdi
Posts: 185
Joined: 03 Aug 2015, 18:48
Location: Germany
Contact:

Re: Objekt-Informationen rekursiv Aufruf

24 Sep 2020, 09:01

Habe nochmals Hand angelegt und wollte Euch das nicht vorenthalten:

Code: Select all

A := {}
A.Name := "Demo Objekt"
A.Zweck := "nur Demo (Objekt hat keinen realen Nutzen)"
A.B := {}
A.B.Zaehler := 1
A.B.C := {}
A.B.C.D := {}
A.B.C.D.a := "VW"
A.B.C.D.b := "BMW"
A.B.C.D.E := {}
A.B.C.D.E.F := {}
A.B.C.D.E.F.G := {}
A.B.C.D.E.F.G.1 := {}
A.B.C.D.E.F.G.1 := {KeyA: "ValueA", KeyB: "ValueB",KeyN: "...", KeyZ: "WertZ"}
; A.B.C.D.E.F.G.2 := A			; Zirkelbezug zum Testen
A.B.C.D.E.F.G.H := "Pedal"
A.B.C.D.1 := "Daimler"

MsgBox % GetAll(A,"A",A_Tab,A_Tab,,A_Tab)
MsgBox % O_GetAll_(A,"A")
Clipboard := O_GetAll_(A)






GetAll(o,oN="",NT="",Ke="",Ve="", WZ="",T="1",V=""){		; fuer die Anzeige eines Objektes	; oN -> Objekt Name		 Nt -> Trenner 	Ke -> KeyEnde		; Ve -> Value Ende 		WZ -> Wert ZuweisugsZeichen		nur intern:	T -> Tiefe			; V -> fuer interne Vaeter
; Aufrufbeispiele:
; MsgBox % GetAll(A,"A",A_Tab,A_Tab,,A_Tab)
; oder ueber O_GetAll_()
	if(T>99)
	{
		SoundBeep,300
		return "Error Abruch wegen Zirkelbezug oder zu hoher Verschachtelungstiefe."
	}
	for key,val in o
	{
		if (IsObject(val))
		{
			ges .=  V NT   key Ke  "`r`n"							; Listet Enden ohne Blaetter
			ges .=  GetAll(val,oN,NT,Ke,Ve,WZ,T+1,V NT key) 		; Listet Rekursiv
		}
		else
			ges .=  V NT    key WZ  val   Ve "`r`n"	  				; Listet Blaetter
	}  
	return ges
}


O_GetAll_(o,oN="",NT=".",Ke="",Ve="", WZ="",T="1"){					; fuer die Anzeige eines Objektes in AHK einlese Schreibweise
; Aufrufbeispiele:
; MsgBox % O_GetAll_(A,"A")
; MsgBox % O_GetAll_(A)

if (WZ="")
	WZ:=" := "
if (WZ=0)
	WZ:=""
if (Ke="")
	Ke:=" := {}"
if (Ke=0)
	Ke:=""
if (oN="")
	oN:="Obj"
	ges := GetAll(o,oN,NT,Ke,Ve, WZ)
	{				; < ----  ueberfluessig 	nachtraeglich geaendert
	  Loop, Parse,ges,`n,`r
		{
			if(Trim(A_LoopField)<>"")
				cges .= oN Trim(A_LoopField) "`n"
		}
	}				; < ----  ueberfluessig 	nachtraeglich geaendert
	if(IsObject(o) and oN<>"")
		cGes := oN Ke "`r`n" cGes
	return cGes
}
Nochmals vielen Dank.
Mit der allgemeinen Anregung, so etwas braucht der Objekt-Neuling. Deshalb sollte so eine Funktion in der AHK-Hilfe vorgestellt werden und besser noch, als AHK-interne Funktion abrufbar sein.
Win 10 Home (x64) and Win 11 Pro N
https://github.com/Grrdi/ZackZackOrdner/archive/master.zip --> get folders on the quick
User avatar
Gerdi
Posts: 185
Joined: 03 Aug 2015, 18:48
Location: Germany
Contact:

Re: Objekt-Informationen rekursiv Aufruf

24 Sep 2020, 16:34

Wenn man die Skript-Ausgabe nicht nur ansehen will, sondern wirklich als Eingabe für neu Skripte verwenden will, dann fehlen bei der vorigen Lösung noch die Hochkommas für die Werte der Objekt-Keys, wenn sie keine Numbers sind. Die Hochkomma Einrahmung der nicht Number Werte schlägt nur zu wenn die betreffenden Default-Einstellungen nicht verändert werden. Des Weiteren wurden 2 Trimm() Funktionen entfernt, die noch Überbleibsel einer älteren Version waren in der die Zeile mit der Rekursion ein "`r`n" am Zeilenende hatte, dadurch entstand Müll der mit Trim entfernt wurde.
Im Beispiel unten lässt der 1. MsgBox-Befehl alle Werte in Hochkommas einrahmen.
Hinweis: 2 Innen-Hochkommas direkt nebeneinander ergeben 1 wirksames. Der 2. MsgBox-Befehl gibt Numbers ohne Hochkommas aus.

Code: Select all

A := {}
A.Name := "Demo Objekt"
A.Zweck := "nur Demo (Objekt hat keinen realen Nutzen)"
A.B := {}
A.B.Zaehler := 1
A.B.KommaZahl := -5.589
A.B.C := {}
A.B.C.D := {}
A.B.C.D.a := "VW"
A.B.C.D.b := "BMW"
A.B.C.D.E := {}
A.B.C.D.E.F := {}
A.B.C.D.E.F.G := {}
A.B.C.D.E.F.G.1 := {}
A.B.C.D.E.F.G.1 := {KeyA: "ValueA", KeyB: "ValueB",KeyN: "...", KeyZ: "WertZ"}
; A.B.C.D.E.F.G.2 := A			; Zirkelbezug zum Testen
A.B.C.D.E.F.G.H := "Pedal"
A.B.C.D.1 := "Daimler"
; HochK="
; Te :=" := " HochK  
MsgBox % O_GetAll_(A,"A",,, """" ," := """)
; MsgBox % O_GetAll_(A,"A",,,HochK,Te)
; MsgBox % GetAll(A,"A",A_Tab,A_Tab,,A_Tab)
MsgBox % O_GetAll_(A,"A")

; Clipboard := O_GetAll_(A)



GetAll(o,oN="",NT="",Ke="",Ve="", WZ="",T="1",V=""){		; fuer die Anzeige eines Objektes	; oN -> Objekt Name		 Nt -> Trenner 	Ke -> KeyEnde		; Ve -> Value Ende 		WZ -> Wert ZuweisugsZeichen		nur intern:	T -> Tiefe			; V -> fuer interne Vaeter
; Aufrufbeispiele:
; MsgBox % GetAll(A,"A",A_Tab,A_Tab,,A_Tab)
; oder ueber O_GetAll_()
	IP := false
	if (WZ = " := " and Ve = "")
		IP := true

	if(T>99)
	{
		SoundBeep,300
		return "Error Abruch wegen Zirkelbezug oder zu hoher Verschachtelungstiefe."
	}
	for key,val in o
	{
		if (IsObject(val))
		{
			ges .=  V NT   key Ke  "`r`n"							; Listet Enden ohne Blaetter
			ges .=  GetAll(val,oN,NT,Ke,Ve,WZ,T+1,V NT key) 		; Listet Rekursiv
		}
		else
		{
			if IP
			{
				if val is not number
					HK="
				else
					HK:=
			}
			ges .=  V NT  key WZ  HK val Ve HK "`r`n"	  			; Listet Blaetter
		}
	}  
	return ges
}


O_GetAll_(o,oN="",NT=".",Ke="",Ve="", WZ="",T="1"){					; fuer die Anzeige eines Objektes in AHK einlese Schreibweise
; Aufrufbeispiele:
; MsgBox % O_GetAll_(A,"A")
; MsgBox % O_GetAll_(A)

if (WZ="")
	WZ:=" := "
else if (WZ=0)
	WZ:=""
if (Ke="")
	Ke:=" := {}"
if (Ke=0)
	Ke:=""
if (oN="")
	oN:="Obj"
	ges := GetAll(o,oN,NT,Ke,Ve, WZ)
	Loop, Parse,ges,`n,`r
	{
		if((A_LoopField)<>"")
			cges .= oN A_LoopField "`r`n"
	}
	if(IsObject(o) and oN<>"")
		cGes := oN Ke "`r`n" cGes
	return cGes
}
Unten folgen jeweils die neueste Funktionen mit Aufrufbeispielen, wobei mein Ziel ist, dass man den Output in eine Datei schreiben kann, die dann über #Include eingelesen werden kann und dadurch ein Duplikat des Ursprünglichen Objektes entsteht.

Code: Select all

; erstellt von einem bestehenden Ahk-Objekt eine Textstring, der mit Ahk als Script eingelesen (z.B. via include), wieder das gleiche Objekt ergibt.
B := [[[6,"Sieben",8],[8,9,10],[10,11]] , [[9,10,11],[11,12,13],[13,14,15]] , [[12,13,14],[14,15,16],[16,17,18]]]
B[1,3,3] := "Zwoelf"
B[2,2,2] := "Zwoelf"
B.1.1.1 := "ZWOELF"
A := {}
A.Name := "Demo Objekt"
A.Zweck := "nur Demo (Objekt hat keinen realen Nutzen)"
A.B := {}
A.B.Zaehler := 1
temp0 := "Komma-Zahl"
A.B[temp0] := -5.589
A.B.WasMitProzent := "-5.589%"
Temp1:="Leerzeichen Key"
Temp2:="Tabulator im" A_Tab "Key"
A.B[Temp1] := {}
A.B[Temp1][Temp2] := "Der Schlüssel-Name ist: Tabulator im" A_Tab "Key"
A.B.C := {}
A.B.C.D := {}
A.B.C.D.a := "VW"
A.B.C.D.b := "BMW"
A.B.C.D.E := {}
A.B.C.D.E.F := {}
A.B.C.D.E.F.G := {}
A.B.C.D.E.F.G.2 := B.1.1
; A[B,C,D,a]:= Porsche
A.B.C.D.E.F.G.1 := {}
A.B.C.D.E.F.G.1 := {KeyA: "ValueA", KeyB: "ValueB",KeyN: "...", KeyZ: "WertZ"}
; A.B.C.D.E.F.G.2 := A			; Zirkelbezug zum Testen
A.B.C.D.E.F.G.H := "Pedal"
A.B.C.D.E.F.G["""Ha""ns"] := "P""ed""al"
A.B.C.D.1 := "Daimler"
; Clipboard :=  GetAll(A,"A",15,A_Tab,A_Tab,,A_Tab)
; Te :=" := " HochK  
; MsgBox % O_GetAll_(A,"A",15,,, """" ," := """)
; MsgBox % GetAll(A,"A",15,A_Tab,A_Tab,,A_Tab)
Clipboard := O_GetAll_(A,"A",11)
MsgBox % Clipboard
; MsgBox % ___KeyA A_Tab ___KeyB A_Tab ___KeyN A_Tab ___KeyZ		; diese Zeile zeigt wie unsauber AHK mit Dynamischen lokalen Variablen umgeht, sie sollte eigentlich nichts anzeigen.

; Hilft bei:
; erstellt von einem bestehenden Ahk-Objekt eine Textstring, der mit Ahk als Script eingelesen (z.B. via include), wieder das gleiche Objekt ergibt.
; dient direkt zur Anzeige von Objekten oder zum Textvergleich 2er Objekte. wenn die Ausgaben 2er Übjekte gleich sind, dann sind auch di Objekte gleich!
GetAll(o,oN="",MT="",NT="",Ke="",Ve="", WZ="",T="1",V=""){		; fuer die Anzeige eines Objektes	; oN -> Objekt Name		 Nt -> Trenner 	Ke -> KeyEnde		; Ve -> Value Ende 		WZ -> Wert ZuweisugsZeichen		nur intern:	T -> Tiefe			; V -> fuer interne Vaeter
; Aufrufbeispiele:
; MsgBox % GetAll(A,"A",A_Tab,A_Tab,,A_Tab)
; oder ueber O_GetAll_()
	IP := false
	if (WZ = " := " and Ve = "")											; wenn Ausnahmebehandlungen gewuenscht
		IP := true
	if(MT="")
		MT := 16
	if(T>MT)
	{
		SoundBeep,300														; Tonsignal bei erreichender willkuerlichen Maximaltiefe
		return A_Tab "Error Abruch wegen Zirkelbezug oder zu hoher Verschachtelungstiefe." A_Tab
	}
	for key,val in o															; Schleife uber alle Key's und Werte des Objektes
	{
		HK2:=""
		if(IP and not TryKey(Key))											; wenn Ausnahmebehandlungen gewuenscht und wenn notwendig
		{
			HK2=``"
			StringReplace,key,key,","",										; "" werden beim Einlesen zu " das gilt auch beim Ruecklesen
		}
			; MsgBox % "Ausnahmebehandlung fuer >>>" Key "<<<"
		if (IsObject(val))
		{																	; wenn Val kein Wert sondern Objekt, dann rekursif tiefer rein
			ges .=  V NT HK2 key HK2 Ke  "`r`n"								; Listet Enden ohne Blaetter
			ges .=  GetAll(val,oN,MT,NT,Ke,Ve,WZ,T+1,V NT HK2 key HK2) 		; Listet Rekursiv		; Rekursiver Aufruf
		}
		else
		{		
			if IP
			{												; wenn Unterscheidung zwischen numerischen und String-Werten gewuenscht
				if val is not number
					HK="													; Werte mit "
				else
					HK:=													; Werte ohne "
			}
			if IP
				StringReplace,val,val,","",All								; "" werden beim Einlesen zu " das gilt auch beim Ruecklesen
			ges .=  V NT HK2 key HK2 WZ HK val Ve HK "`r`n"	  				; Listet Blaetter
		}
	}  
	return ges
}
TryKey(Var){		; Prueft Key-Variable ob der Key in der Notation Obj.Key := Val vertraeglich ist.
	try
	{
		___%Var% := "egal " 					; wegen der Schwachstelle in AHK, locale Variablen nicht konsequent lokal zu lassen, werden   hier die 3mal Unterstrich Variablen eingefuehrt. Vorschlag: Die ___Vars werden nur in Funktionen verwendet, in Hauptprogrammen sind sie nur bei sofortiger Verwendung erlaubt, da sie ja von Funktionen dynamisch veraendert werden koennten. 
		if(Var = "")
			return 0
		if(___%Var%) = ""
			return 0
	}
	catch
		return 0
return 1
}
	
; erstellt von einem bestehenden Ahk-Objekt eine Textstring, der mit Ahk als Script eingelesen (z.B. via include), wieder das gleiche Objekt ergibt.
O_GetAll_(o,oN="",MT="",NT=".",Ke="",Ve="", WZ="",T="1"){					; fuer die Anzeige eines Objektes in AHK einlese Schreibweise
; Aufrufbeispiele:
; MsgBox % O_GetAll_(A,"A")
; MsgBox % O_GetAll_(A)
KN := {}
if (WZ="")
	WZ:=" := "
else if (WZ=0)
	WZ:=""
if (Ke="")
	Ke:=" := {}"
if (Ke=0)
	Ke:=""
if (oN="")
	oN:="Obj"
	ges := GetAll(o,oN,MT,NT,Ke,Ve, WZ)						; rekursive Funktion aufrufen
	Loop, Parse,ges,`n,`r
	{														; erhaltene Zeilen einzeln bearbeiten
		if((A_LoopField)<>"")								; Leezeilen auslassen
		{
			LoopField :=
			Ers := StrSplit(A_LoopField,"``""")				; trennen bei `"
			if(Ers.MaxIndex()>1)							; wenn Ausnahme
			{						; Ja					; VorZeilen Schreiben + ObjektNamen vorne in Zeile einfuegen
				G=0
				Loop % Ers.MaxIndex()
				{											; Schleife ueber Elemente zwischen `"
					++G
					if(G=2)									; von gerader Indexnummer ausgehend
					{										; zusammenschreiben
						VZ .= "____" A_Index " := """ Ers[A_Index] """`r`n"	; Vorzeile schreiben
						G=0
						LoopField .= SubStr(Ers[A_Index-1],1,-1)			; HauptZeilenElement vor Ausnahme zufügen
						LoopField .= "["  "____" A_Index "]"				; HauptZeilenElement Ausnahme zufügen
						if(A_Index +1 = Ers.MaxIndex())						; wenn Element wegen Schleifen-Maximal-Index nicht berucksichtigt wuerde
							LoopField .= Ers[A_Index+1]						; HauptZeilenElement nach Ausnahme zufügen
					}
				}
				cges .= VZ oN LoopField "`r`n"								; HauptZeilenElemente allen Zeilen zufuegen
				VZ :=
			}
			else
				cges .= oN A_LoopField "`r`n"				; Nein			; ObjektNamen vorne in Zeile einfuegen
		}
	}
	if(IsObject(o) and oN<>"")
		cGes := oN Ke "`r`n" cGes											; WurzelElement vorne zufuegen
	return cGes
}
Win 10 Home (x64) and Win 11 Pro N
https://github.com/Grrdi/ZackZackOrdner/archive/master.zip --> get folders on the quick

Return to “Ich brauche Hilfe”

Who is online

Users browsing this forum: gero and 23 guests