Code-1: (Correct)
- Code: Select all Expand view RUN
@ 40, 20 SAY aPrompts[ 1 ] SIZE 80,24 PIXEL OF oDlg
@ 40,110 GET aGets [ 1 ] VAR aValues[ 1 ] SIZE 120,28 PIXEL OF oDlg
@ 70, 20 SAY aPrompts[ 2 ] SIZE 80,24 PIXEL OF oDlg
@ 70,110 GET aGets [ 2 ] VAR aValues[ 2 ] SIZE 120,28 PIXEL OF oDlg
@ 100, 20 SAY aPrompts[ 3 ] SIZE 80,24 PIXEL OF oDlg
@ 100,110 GET aGets [ 3 ] VAR aValues[ 3 ] SIZE 120,28 PIXEL OF oDlg
@ 130, 20 SAY aPrompts[ 4 ] SIZE 80,24 PIXEL OF oDlg
@ 130,110 GET aGets [ 4 ] VAR aValues[ 4 ] SIZE 120,28 PIXEL OF oDlg
This works well.
But where there are many values, we would like to create the Says and Gets in a loop we may write code something like this:
Code-2: (Wrong)
- Code: Select all Expand view RUN
nRow := 40
for n := 1 to nLen
@ nRow, 20 SAY aPrompts[ n ] SIZE 80,24 PIXEL OF oDlg
@ nRow,110 GET aGets[ n ] VAR aValues[ n ] ;
SIZE 120,28 PIXEL OF oDlg
nRow += 30
next
But this does not work. We get a runtime error.
Reason: For every Get, its bSetGet codeblock is assigned with
{ |u| If( PCount() == 0, aValues[ n ], aValues[ n ] := u ) }.
During runtime this codeblock is evaluated with the value of 'n', which is always nLen+1 and array bound error occurs.
To overcome this problem, we need to create the Gets in a separate function using the concept of detatched locals. Here is a working sample using this principle.
Code-3: (Correct working sample)
- Code: Select all Expand view RUN
- #include "fivewin.ch"
function Main()
local oDlg
local aPrompts := { "First", "Second", "Third", "Fourth" }
local aValues := { Space( 10 ), Space( 10 ), Space( 10 ), Space( 10 ) }
local aGets[ 4 ], n, nRow
DEFINE DIALOG oDlg SIZE 400,250 PIXEL TRUEPIXEL
nRow := 40
for n := 1 to 4
@ nRow, 20 SAY aPrompts[ n ] SIZE 80,24 PIXEL OF oDlg
aGets[ n ] := CreateGet( nRow, 110, aValues, n, oDlg )
nRow += 30
next
@ nRow, 20 BUTTON "Close" SIZE 100,30 PIXEL OF oDlg ACTION oDlg:End()
ACTIVATE DIALOG oDlg CENTERED
XBROWSER aValues // Ceck the values
return nil
function CreateGet( nRow, nCol, aArray, nEle, oDlg )
local oGet
@ nRow, nCol GET oGet VAR aArray[ nEle ] SIZE 120,24 PIXEL OF oDlg
return oGet
Enhacement in FWH 18.08:
It is no more necessary to create the Gets in a separate function. We can create the gets straight away in the loop iteslef in a single command. This is a working sample, using the new clause SUBSCTIPT:
Syntax:
@ r, c GET aArray SUBSCRIPT n // where n is the loop variable
Code-4: ( Correct FWH 18.08 )
- Code: Select all Expand view RUN
- #include "fivewin.ch"
function Main()
local oDlg
local aPrompts := { "First", "Second", "Third", "Fourth" }
local aValues := { Space( 10 ), Space( 10 ), Space( 10 ), Space( 10 ) }
local aGets[ 4 ], n, nRow := 40
DEFINE DIALOG oDlg SIZE 400,250 PIXEL TRUEPIXEL
nRow := 40
for n := 1 to 4
@ nRow, 20 SAY aPrompts[ n ] SIZE 80,24 PIXEL OF oDlg
@ nRow,110 GET aGets[ n ] VAR aValues SUBSCRIPT n ;
SIZE 120,28 PIXEL OF oDlg
nRow += 30
next
@ nRow, 20 BUTTON "Close" SIZE 100,30 PIXEL OF oDlg ACTION oDlg:End()
ACTIVATE DIALOG oDlg CENTERED
XBROWSER aValues
return nil
Let us now consider a bit more complex case of a multi dimentional array consisting of Prompts in the first column, variables in the second column and pictures in the third column. Here the get variable is aData[ n, 2 ] where n is the loop variable.
In this sample, let us also try using the recently introduced syntax:
@ r, c SAY ...GET ...
Code-5 (Working sample FWH 1808)
- Code: Select all Expand view RUN
function ArrayGets
local oDlg
local aData := { { "First ", Space( 10 ), nil }, ;
{ "Second ", Space( 10 ), "@!" }, ;
{ "Third ", DATE(), "@D" }, ;
{ "Fourth ", 0, "99,999.99" } }
local aGets[ 4 ], n, nRow
DEFINE DIALOG oDlg SIZE 400,250 PIXEL TRUEPIXEL
nRow := 40
for n := 1 to 4
@ nRow, 20 SAY aData[ n, 1 ] GET aGets[ n ] VAR aData SUBSCRIPT n, 2 ;
PICTURE aData[ n, 3 ] SIZE 240,28 PIXEL OF oDlg
nRow += 30
next
@ nRow, 20 BUTTON "Close" SIZE 100,30 PIXEL OF oDlg ACTION oDlg:End()
ACTIVATE DIALOG oDlg CENTERED
XBROWSER aData // Check
return nil
This enhancement in FWH 1808 makes programming Gets of arrays using loop variables.
This new syntax is not applicable to gets from resources as such gets are not generally redefined in a loop.