ONLINE HELP
 WINDEVWEBDEV AND WINDEV MOBILE

This content has been translated automatically.  Click here  to view the French version.
Help / WLanguage / WLanguage syntax / WLanguage procedures
  • Principle
  • Declaring and calling internal procedures
  • Example
  • Characteristics of internal procedures
  • Use in callback
  • Internal Procedure parameter
  • Access to the variables from an internal procedure
  • Nesting internal procedures
  • Sibling internal procedures
  • Recursive calls
  • Named parameters
  • Dynamic compilation
  • Internal procedure and extension attributes
  • Special case: using internal procedures with asynchronous functions
  • Limitations
WINDEV
WindowsLinuxJavaReports and QueriesUser code (UMC)
WEBDEV
WindowsLinuxPHPWEBDEV - Browser code
WINDEV Mobile
AndroidAndroid Widget iPhone/iPadIOS WidgetApple WatchMac Catalyst
Others
Stored procedures
Principle
Several features require a procedure called once or several times via a WLanguage function ("Callback"). For example, the following functions are in this case: fListFile, TreeListItem, AlbumPicker in iOS, etc.
A procedure must be created for these functions but several drawbacks appear:
  • Loss of code locality: it is not possible to see the final algorithm as a whole. Several backs and forths must be performed between the calling code and the WLanguage procedure.
  • Difficulty sharing information with the WLanguage procedure: It is generally necessary to use global variables (to pass parameters to the callback or retrieve results).
In this case, the internal procedures are used to simplify the writing of callback features and to fix the problems caused when using a standard procedure.
Declaring and calling internal procedures
An internal procedure is declared in the code of an existing process (process associated with a control, window procedure, global procedure or class method, ...).
The syntax is as follows:
PROCEDURE INTERNE <Nom de la procédure>()
<Code de la procédure>
FIN
Remarks:
  • The internal procedures must be declared in the process where they are used.
  • Parameter input assistance is activated: a tooltip specifying the type of parameter expected is displayed when the internal procedure call is entered..
  • The processing code before and after the internal procedure declaration code is executed in sequence: the internal procedure code is not executed..
    Example:
    // Code avant la procédure Interne: Ce code est exécuté. 
    INTERNAL PROCEDURE MaProcédureInterne()
    	// Code de la procédure interne. 
    	// Ce code n'est pas exécuté. 
    END
    // Code après la procédure interne: Ce code est exécuté.
  • An internal procedure can be directly called by its name, like any standard procedure. This call can be placed before or after the declaration of internal procedure.
    Example:
    // Appel placé avant
    MaProcédureInterne()
    
    // Déclaration de la procédure interne
    INTERNAL PROCEDURE MaProcédureInterne()
    	// Code de la procédure interne exécuté lors de l'appel à MaProcédureInterne()
    END
    
    // Appel placé après
    MaProcédureInterne()

    This allows you to get a code that is easy to read.
  • The exceptions triggered by the internal procedures can be processed outside the internal procedure.
WINDEVWEBDEV - Server code

Example

The following code is used to list all child elements of a node found in a TreeView control:
// Liste les "fils" du noeud "Desserts" dans le champ Arbre "ARBRE_RecetteTV"
// La procédure "DérouleTout" est appelée
// pour chaque "fils" trouvé du noeud "Desserts"
Res = TreeListItem(ARBRE_RecetteTV, "Recettes" + TAB + "Desserts", DérouleTout)

INTERNAL PROCEDURE DérouleTout(ARBRE_RecetteTV, CheminFils, FilsTrouvé, Niveau, Pointeur)
	// L'élément trouvé est-il une feuille?
	IF TreeTypeItem(ARBRE_RecetteTV, CheminFils + FilsTrouvé) = tvLeaf THEN
		RETURN // Retour à la fonction ArbreListeFils
	ELSE
		// L'élément trouvé est-il enroulé?
		IF TreeStatus(ARBRE_RecetteTV, CheminFils + FilsTrouvé) = tvCollapse THEN
			TreeExpand(ARBRE_RecetteTV, CheminFils + FilsTrouvé)
		END
	END
	// Enroule le champ Arbre
	TreeCollapse(ARBRE_RecetteTV, "Recettes")
END
Characteristics of internal procedures

Use in callback

The internal procedure can be used in a WLanguage functions that expects a WLanguage procedure as parameter (like fListFile, TreeListItem, ...).
Warning: In this case, the parameter corresponding to the internal procedure name must correspond directly to the internal procedure name (the procedure name must not be enclosed in quotation marks)..
No to do:
// Liste les "fils" du noeud "Desserts" dans le champ Arbre "ARBRE_RecetteTV"
Res = TreeListItem(ARBRE_RecetteTV, "Recettes" + TAB + "Desserts", "DérouleTout")

INTERNAL PROCEDURE DérouleTout(ARBRE_RecetteTV, CheminFils, FilsTrouvé, Niveau, Pointeur)
	...
END
Do:
// Liste les "fils" du noeud "Desserts" dans le champ Arbre "ARBRE_RecetteTV"
Res = TreeListItem(ARBRE_RecetteTV, "Recettes" + TAB + "Desserts", DérouleTout)

INTERNAL PROCEDURE DérouleTout(ARBRE_RecetteTV, CheminFils, FilsTrouvé, Niveau, Pointeur)
	...
END

Internal Procedure parameter

The internal procedure can be used as parameter in a procedure. In this case, the parameter type will be "Procedure".
Example:
// Déclaration de la procédure interne
INTERNAL PROCEDURE MaProcédureInterne()
	// code exécuté lors de l'appel de la procédure passée en paramètre
END

MonAutreProcédure(MaProcédureInterne)
PROCEDURE MonAutreProcédure(p is procedure)

p()
AndroidAndroid Widget Java This feature is not available.

Access to the variables from an internal procedure

The variables declared in the same process as the declaration of internal procedure can be called in the internal procedure. There is no need to use global variables anymore. This concept is called "Closure".
Example:
sListeElément is string
sSéparateur is string = RC
TreeListItem(ARBRE_ChampArbre, "", MaProcédureInterne)

INTERNAL PROCEDURE MaProcédureInterne(NomArbre, Branche)
	sListeElément += [sSéparateur] + Branche
END

Nesting internal procedures

The internal procedures can be nested. Each internal procedure can access the variables of procedures that include it.
Example:
VariableExterne is int
Trace(VariableExterne)
MaProcédureInterne1()
INTERNAL PROCEDURE MaProcédureInterne1()
	VariableInterne1 is int
	Trace(VariableExterne + VariableInterne1)
	MaProcédureInterne2()
	INTERNAL PROCEDURE MaProcédureInterne2()
		VariableInterne2 is int
		Trace(VariableExterne + VariableInterne1 + VariableInterne2)
	END
END

Sibling internal procedures

Two internal procedures found in the same procedure can be called between themselves (sibling internal procedures).
Example:
INTERNAL PROCEDURE MaProcédurePrincipale()

	INTERNAL PROCEDURE MaProcédureInterne1()
		...
	END

	INTERNAL PROCEDURE MaProcédureInterne2()
		...
		// Appel de la procédure soeur
		MaProcédureInterne1()
	END
END

Recursive calls

An internal procedure can be called itself in recursive way.

Named parameters

If an internal procedure includes parameters with default values, you have the ability to call the internal procedure by naming its parameters. Two syntaxes are possible:
  • Single-line named parameters,
  • Multiline named parameters.
For more details, see Named parameters in a procedure.

Dynamic compilation

You can use an internal procedure in a dynamically compiled code (with Compile, for example).
Example:
lsCode is string = [
// Code compilé dynamiquement
sListeElément est une chaîne
sSéparateur est une chaîne = RC
ArbreListeFils(ARBRE_ChampArbre, "", MaProcédureInterne)

PROCEDURE INTERNE MaProcédureInterne(NomArbre, Branche)
	sListeElément += [sSéparateur] + Branche
FIN

]

lsRésultat is string

lsRésultat = Compile("MaProc",lsCode)

Internal procedure and extension attributes

extension attributes can be used with internal procedures. For example, a single process can run an internal procedure in a secondary thread, then call a second procedure in the main thread to refresh the interface.
Example:
// Code d'un bouton par exemple ...
ExécutionAsynchrone()

INTERNAL PROCEDURE ExécutionAsynchrone() <thread>

	// Ici exécution d'un traitement en tâche de fond
	// dans un thread secondaire (pas d'accès à l'interface)
	ThreadPause(5 s)

	// Traitement terminé, rappel d'un traitement du thread principal 
	// donc autorisé à mettre à jour l'interface
	AprèsExécutionAsynchrone()
END

INTERNAL PROCEDURE AprèsExécutionAsynchrone() <main thread>
	Trace("Terminé ...")
END
Special case: using internal procedures with asynchronous functions
Internal procedures can be used as callbacks for asynchronous functions..
WARNING: In this case, the code located after the call to the function using an asynchronous WLanguage procedure will be executed BEFORE the code of the Internal procedure..
Example: In this WINDEV Mobile example, the code after AlbumPicker will be executed BEFORE the internal procedure. The internal procedure will be called when the picker is validated by the user.
AlbumPicker(albumImage, SélectionPhoto)
INTERNAL PROCEDURE SélectionPhoto(sCheminImage)
	IMG_ChampImage = sCheminImage
END
// Code exécuté après la fonction AlbumSélecteur mais 
// AVANT le code de la procédure interne.
Limitations
  • An internal procedure cannot be named like the procedures that contain it.
  • Two internal procedures of same level cannot have the same name, even if they are declared in different code blocks (IF THEN ELSE, ...).
  • The internal procedures are not available in dynamic compilation.
  • The execution of an internal procedure cannot be automated.
  • The automatic management of errors is not available for the internal procedures.
  • AndroidAndroid Widget Java If the option "Scope of local variables limited to current block " is enabled in the "Compilation" tab of the project description, declaring internal procedures using variables "with scope limitation" will result in a generation error.. Example:
    • the following code causes a compilation error:
      PROCEDURE MaProcedure()
      IF MaCondition THEN
          str is string // str n'existe que dans la portée de l'instruction SI 
          INTERNAL PROCEDURE ma_proc_interne()
              str = "truc" // -> Fera une erreur à la génération Java/Android
          END
      END
    • To correct this code, it is necessary not to declare the variable in the IF statement:
      PROCEDURE MaProcedure()
      str is string 
      IF MaCondition THEN
          INTERNAL PROCEDURE ma_proc_interne()
              str = "truc"
          END
      END
    In Java and Android, we recommend always declaring internal procedures in the scope of the procedure itself.. Thus, if undeclared variables are used, compilation errors will be displayed.
Minimum version required
  • Version 20
This page is also available for…
Comments
Click [Add] to post a comment

Last update: 09/19/2024

Send a report | Local help