Wert-Übergabe an Codeblöcke?!

Alle Fragen um die Programmierung, die sich sonst nicht kategorisieren lassen. Von Makro bis Codeblock, von IF bis ENDIF

Moderator: Moderatoren

Antworten
Benutzeravatar
Markus Walter
Programmier-Gott
Programmier-Gott
Beiträge: 1018
Registriert: Di, 24. Jan 2006 10:22
Wohnort: Saarland

Wert-Übergabe an Codeblöcke?!

Beitrag von Markus Walter »

Hi,

ich versuche gerade den Schleifenzähler an einen Codeblock zu übergeben. Nun wird bei dem Codeblock offenbar die Referenz auf die Zählervariable abgelegt und bei der Ausführung des Codeblocks der zu diesem Zeitpunkt gültige Wert der Zählervariablen verwendet.

Wie kann ich erreichen, dass im Codeblock der "richtige" Zählerwert zur Verfügung steht?

Einfaches Beispiel mit Pushbuttons:

Code: Alles auswählen

#include "appevent.ch"


procedure main()
LOCAL nEvent, mp1, mp2, oXbp
local i, xPos := 100

  SetColor("N/W")

  CLS


  for i := 1 to 5
    oXbp := XbpPushButton():new()
    oXbp:caption := alltrim(str(i))
    oXbp:create( , , {xPos,20}, {40,20} )
    oXbp:activate:= {|| msgBox(str(i)) }
    xPos += 50
  next


  // Event loop = Programmsteuerung

  nEvent := 0
  DO WHILE nEvent <> xbeP_Close

     nEvent := AppEvent( @mp1, @mp2, @oXbp )

     oXbp:HandleEvent( nEvent, mp1, mp2 )

  ENDDO

RETURN

Die Beschriftung der Buttons ist richtig (1, 2, ..., 5). Beim Drücken eines der Buttons zeigt die Messagebox immer "6" an (der dann in der Variablen i gespeicherte Wert). Ich bräuchte hier aber die Werte zum Zeitpunkt des Schleifendurchlauf (1, 2, ..., 5).

Stehe ich jetzt ganz auf dem Schlauch? (Habe mich schon einen halben Meter zur Seite gesetzt... :wink: )

Kann jemand helfen?
Gruß
Markus

Mitglied der XUG Saarland-Pfalz
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16517
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

Hallo Markus,
Du musst diesem Problem mit den "detached locals" begegnen, sonst geht das nicht!
Also in Deiner Messagebox nicht Str(i) als Parameter, sondern eine eigene Funktion bauen:

Code: Alles auswählen

oXbp:activate:= &MeineFunkt( i )


Procedure MeineFunkt( a )
return "{ || msgBox( str( a ) ) }"
Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
andreas
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 1902
Registriert: Mi, 28. Sep 2005 10:53
Wohnort: Osnabrück
Hat sich bedankt: 4 Mal
Kontaktdaten:

Beitrag von andreas »

Hallo Markus,

vielleicht könntest du dafür auch Cargo-Variable benutzen, um dort die Nummer abzulegen.

Code: Alles auswählen

oXbp:cargo := i
oXbp:activate := {| uNIL1, uNIL2, oX | msgbox( str(oX:cargo) ) }
Gruß,

Andreas
VIP der XUG Osnabrück
Benutzeravatar
Markus Walter
Programmier-Gott
Programmier-Gott
Beiträge: 1018
Registriert: Di, 24. Jan 2006 10:22
Wohnort: Saarland

Beitrag von Markus Walter »

Hallo Martin,

habe mir die Hilfe zu dem Thema "Detached Locals" sehr genau durchgelesen. Ich glaube Du verwechselst da was. Mit "Detached Locals" werden die Variablen bezeichnet, die durch die Verwendung in einem Codeblock die Ausführungszeit "Ihrer" Funktion überdauern. Aus der Hilfe zu "Detached Locals":

Code: Alles auswählen

   PROCEDURE Main 
      LOCAL bBlock := SaveCursor()     // Position sichern 

 
      @ 10, 20 SAY "Cursor-Position ist geändert" 
 
      Eval( bBlock )                   // Position restaurieren 
   RETURN 

  FUNCTION SaveCursor() 
      LOCAL nRow := Row()              // LOCAL Variablen 
      LOCAL nCol := Col()              // initialisieren 
 
   RETURN {|| SetPos( nRow, nCol ) }   // In Codeblock einbauen und                                    zurückgeben 
Hier überleben quasi die beiden Variablen nRow und nCol die Ausführungszeit der Funktion in der sie local deklariert worden sind und stehen noch zur Ausführungszeit des Codeblock zur Verfügung.


Bei mir ist es aber andersherum, ich verwende in einem Codeblock eine local Variable (meinen Zähler). Der Codeblock merkt sich die Referenz auf diese Variable und greift zu seiner Ausführungszeit darauf zu. Zu diesem Zeitpunkt ist die Variable aber hochgezählt. Somit geben alle Buttons eine "6" in der Messagebox aus...
Ich möchte erreichen, dass der Codeblock den Wert nicht zur Ausführungszeit, sondern zur Codeblock-Deklarations-Zeit (was für ein Wort) nimmt...

Idee?
Gruß
Markus

Mitglied der XUG Saarland-Pfalz
Benutzeravatar
Markus Walter
Programmier-Gott
Programmier-Gott
Beiträge: 1018
Registriert: Di, 24. Jan 2006 10:22
Wohnort: Saarland

Beitrag von Markus Walter »

Hallo Andreas,

das würde in diesem Fall in der Tat helfen. Aber das ist leider nur ein Beispiel...

Im konkreten Fall erzeuge ich in einer Schleife Codeblöcke. Und in der Funktion in diesen Codeblöcken brauche ich die Schleifenvariable.

Ungefähr so:

Code: Alles auswählen

for i := 1 to 10
  aadd(aBlocks, {|| MyFunction(i) })
next

eval(aBlocks[1])
eval(aBlocks[2])
...

In der Funktion MyFunction soll nun als i eben 1 bis 10 ankommen. Der Codeblock merkt sich aber die Referenz auf i. Zur Ausführungszeit des Codeblocks ist i aber 11, so dass jedesmal die Funktion MyFunction mit dem Parameter 11 arbeitet (statt mit 1 bis 10).
Gruß
Markus

Mitglied der XUG Saarland-Pfalz
Benutzeravatar
andreas
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 1902
Registriert: Mi, 28. Sep 2005 10:53
Wohnort: Osnabrück
Hat sich bedankt: 4 Mal
Kontaktdaten:

Beitrag von andreas »

Versuch es so:

Code: Alles auswählen

aadd(aBlocks, &"{|| MyFunction("+str(i)+") }")
Ich galaube, dass Martin es änlich meinte.
Gruß,

Andreas
VIP der XUG Osnabrück
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16517
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

Hallo Andreas,
ja - genau!
@Markus: nein, das war keine Verwechslung: genau das war gemeint! Auch in Deinem Beispiel wird der Zustand aktuell gespeichert und zurückgegeben. Ansonsten wäre es auch der Zustand nach dem Beenden des Says...

Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Markus Walter
Programmier-Gott
Programmier-Gott
Beiträge: 1018
Registriert: Di, 24. Jan 2006 10:22
Wohnort: Saarland

Beitrag von Markus Walter »

Hallo Andeas,
hallo Martin,

BINGO!!

So geht es. Vielen Danke für Eure Mühe...
Gruß
Markus

Mitglied der XUG Saarland-Pfalz
Benutzeravatar
andreas
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 1902
Registriert: Mi, 28. Sep 2005 10:53
Wohnort: Osnabrück
Hat sich bedankt: 4 Mal
Kontaktdaten:

Beitrag von andreas »

Hallo Markus,

ich freue mich, dass es dir geholfen hat.
Gruß,

Andreas
VIP der XUG Osnabrück
Antworten