Code-1: (Correct)
Code: Select all
@ 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
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
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
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
#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
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
#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
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
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 new syntax is not applicable to gets from resources as such gets are not generally redefined in a loop.