Seite 1 von 1

Wert-Übergabe an Codeblöcke?!

Verfasst: Mo, 26. Jun 2006 14:48
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?

Verfasst: Mo, 26. Jun 2006 15:20
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

Verfasst: Mo, 26. Jun 2006 16:01
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) ) }

Verfasst: Mo, 26. Jun 2006 16:36
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?

Verfasst: Mo, 26. Jun 2006 16:43
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).

Verfasst: Mo, 26. Jun 2006 16:59
von andreas
Versuch es so:

Code: Alles auswählen

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

Verfasst: Mo, 26. Jun 2006 17:03
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

Verfasst: Mo, 26. Jun 2006 17:58
von Markus Walter
Hallo Andeas,
hallo Martin,

BINGO!!

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

Verfasst: Mo, 26. Jun 2006 18:13
von andreas
Hallo Markus,

ich freue mich, dass es dir geholfen hat.