DOCUMENTATION EN LIGNE
DE WINDEVWEBDEV ET WINDEV MOBILE

PV

Aide / WLangage / Syntaxe WLangage / Procédures WLangage
  • Principe
  • Déclaration et appel des procédures internes
  • Exemple
  • Caractéristiques des procédures internes
  • Utilisation en callback
  • Paramètre de type Procédure interne
  • Accès aux variables depuis une procédure interne
  • Imbrication de procédures internes
  • Procédures internes soeurs
  • Appels récursifs
  • Paramètres nommés
  • Compilation dynamique
  • Procédure interne et attributs d'extension
  • Cas particulier : Utilisation de procédures internes avec des fonctions asynchrones
  • Limitations
WINDEV
WindowsLinuxJavaEtats et RequêtesCode Utilisateur (MCU)
WEBDEV
WindowsLinuxPHPWEBDEV - Code Navigateur
WINDEV Mobile
AndroidWidget AndroidiPhone/iPadWidget IOSApple WatchMac Catalyst
Autres
Procédures stockées
Principe
De nombreuses fonctionnalités nécessitent une procédure appelée une ou plusieurs fois au travers d'une fonction du WLangage (également appelée "Callback"). Par exemple, les fonctions suivantes sont dans ce cas : fListeFichier, ArbreListeFils, AlbumSélecteur en iOS, etc.
Il est nécessaire de créer une procédure pour ces fonctions, mais de nombreux inconvénients apparaissent :
  • Perte de la localité du code : Il n'est pas possible de voir l'algorithme final dans son ensemble. Il est nécessaire de faire des aller-retour entre le code appelant et la procédure WLangage.
  • Difficulté de partage d'informations avec la procédure WLangage : Il est en général nécessaire d'utiliser des variables globales (pour passer des paramètres à la callback ou récupérer les résultats).
Dans ce cas, les procédures internes permettent de simplifier l'écriture des fonctionnalités à callback et de simplifier les problèmes posés par l'utilisation d'une procédure classique.
Déclaration et appel des procédures internes
La déclaration d'une procédure interne se fait directement dans le code d'un traitement existant (traitement associé à un champ, procédure de fenêtre, procédure globale ou méthode de classe, ...).
La syntaxe est la suivante :
PROCEDURE INTERNE <Nom de la procédure>()
<Code de la procédure>
FIN
Remarques :
  • Les procédures internes doivent être déclarées dans le traitement dans lequel elles sont utilisées.
  • L'assistance à la saisie des paramètres est activée : une bulle d'aide précisant le type du paramètre attendu est affichée lors de la saisie de l'appel de la procédure interne.
  • Le code du traitement situé avant et après le code de déclaration de la procédure interne est exécuté en séquence : le code de la procédure interne n'est pas exécuté.
    Exemple :
    // Code avant la procédure Interne : Ce code est exécuté. 
    PROCÉDURE INTERNE MaProcédureInterne()
    	// Code de la procédure interne. 
    	// Ce code n'est pas exécuté. 
    FIN
    // Code après la procédure interne : Ce code est exécuté.
  • Il est possible d'appeler directement une procédure interne par son nom, comme pour une procédure classique. Cet appel peut être placé avant ou après la déclaration de la procédure interne.
    Exemple :
    // Appel placé avant
    MaProcédureInterne()
    
    // Déclaration de la procédure interne
    PROCÉDURE INTERNE MaProcédureInterne()
    	// Code de la procédure interne exécuté lors de l'appel à MaProcédureInterne()
    FIN
    
    // Appel placé après
    MaProcédureInterne()

    Il est ainsi possible d'obtenir un code plus simple à lire.
  • Les exceptions provoquées par les procédures internes peuvent être traitées à l'extérieur de la procédure interne.
WINDEV

Exemple

Le code suivant permet de lister tous les éléments fils d'un noeud d'un champ Arbre :
// 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 = ArbreListeFils(ARBRE_RecetteTV, "Recettes" + TAB + "Desserts", DérouleTout)

PROCÉDURE INTERNE DérouleTout(ARBRE_RecetteTV, CheminFils, FilsTrouvé, Niveau, Pointeur)
	// L'élément trouvé est-il une feuille ?
	SI ArbreTypeElément(ARBRE_RecetteTV, CheminFils + FilsTrouvé) = aFeuille ALORS
		RETOUR // Retour à la fonction ArbreListeFils
	SINON
		// L'élément trouvé est-il enroulé ?
		SI ArbreEtat(ARBRE_RecetteTV, CheminFils + FilsTrouvé) = aEnroule ALORS
			ArbreDéroule(ARBRE_RecetteTV, CheminFils + FilsTrouvé)
		FIN
	FIN
	// Enroule le champ Arbre
	ArbreEnroule(ARBRE_RecetteTV, "Recettes")
FIN
Caractéristiques des procédures internes

Utilisation en callback

La procédure interne peut être utilisée dans une fonction du WLangage qui attend une procédure WLangage en paramètre (comme fListeFichier, ArbreListeFils, ...).
Attention : Dans ce cas, le paramètre correspondant au nom de la procédure interne doit correspondre directement au nom de la procédure interne (le nom de la procédure ne doit pas être entre guillemets).
Ne pas faire :
// Liste les "fils" du noeud "Desserts" dans le champ Arbre "ARBRE_RecetteTV"
Res = ArbreListeFils(ARBRE_RecetteTV, "Recettes" + TAB + "Desserts", "DérouleTout")

PROCÉDURE INTERNE DérouleTout(ARBRE_RecetteTV, CheminFils, FilsTrouvé, Niveau, Pointeur)
	...
FIN
Faire :
// Liste les "fils" du noeud "Desserts" dans le champ Arbre "ARBRE_RecetteTV"
Res = ArbreListeFils(ARBRE_RecetteTV, "Recettes" + TAB + "Desserts", DérouleTout)

PROCÉDURE INTERNE DérouleTout(ARBRE_RecetteTV, CheminFils, FilsTrouvé, Niveau, Pointeur)
	...
FIN

Paramètre de type Procédure interne

La procédure interne peut être utilisée comme paramètre dans une procédure. Dans ce cas le type du paramètre sera de type "Procédure".
Exemple :
// Déclaration de la procédure interne
PROCÉDURE INTERNE MaProcédureInterne()
	// code exécuté lors de l'appel de la procédure passée en paramètre
FIN

MonAutreProcédure(MaProcédureInterne)
PROCÉDURE MonAutreProcédure(p est une procédure)

p()
Java Cette fonctionnalité n'est pas disponible.

Accès aux variables depuis une procédure interne

Les variables déclarées dans le même traitement que la déclaration de la procédure interne peuvent être appelées dans la procédure interne. Il n'est plus nécessaire d'utiliser des variables globales. Ce concept est appelé "Closure".
Exemple :
sListeElément est une chaîne
sSéparateur est une chaîne = RC
ArbreListeFils(ARBRE_ChampArbre, "", MaProcédureInterne)

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

Imbrication de procédures internes

Les procédures internes peuvent être imbriquées. Chaque procédure interne peut accéder aux variables des procédures qui l'incluent.
Exemple :
VariableExterne est un entier
Trace(VariableExterne)
MaProcédureInterne1()
PROCÉDURE INTERNE MaProcédureInterne1()
	VariableInterne1 est un entier
	Trace(VariableExterne + VariableInterne1)
	MaProcédureInterne2()
	PROCÉDURE INTERNE MaProcédureInterne2()
		VariableInterne2 est un entier
		Trace(VariableExterne + VariableInterne1 + VariableInterne2)
	FIN
FIN

Procédures internes soeurs

Deux procédures internes présentes dans la même procédure peuvent s'appeler entre elles (procédures internes soeurs).
Exemple :
PROCÉDURE INTERNE MaProcédurePrincipale()

	PROCÉDURE INTERNE MaProcédureInterne1()
		...
	FIN

	PROCÉDURE INTERNE MaProcédureInterne2()
		...
		// Appel de la procédure soeur
		MaProcédureInterne1()
	FIN
FIN

Appels récursifs

Une procédure interne peut s'appeler elle-même de façon récursive.

Paramètres nommés

Si une procédure interne possède des paramètres avec des valeurs par défaut, il est possible d'appeler la procédure interne en nommant ses paramètres. Deux syntaxes sont possibles :
  • Paramètres nommés monolignes,
  • Paramètres nommés multilignes.
Pour plus de détails, consultez Paramètres nommés dans une procédure.

Compilation dynamique

Il est possible d'utiliser une procédure interne dans un code compilé dynamiquement (avec la fonction Compile par exemple).
Exemple :
lsCode est chaîne = [
// 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 est chaîne

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

Procédure interne et attributs d'extension

Les attributs d'extensions peuvent être utilisés avec les procédures internes. Par exemple, un traitement unique peut exécuter une procédure interne dans un thread secondaire pour ne pas être bloquant, puis appeler une seconde procédure dans le thread principal pour mettre à jour l'interface.
Exemple :
// Code d'un bouton par exemple ...
ExécutionAsynchrone()

PROCÉDURE INTERNE 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()
FIN

PROCÉDURE INTERNE AprèsExécutionAsynchrone() <thread principal>
	Trace("Terminé ...")
FIN
Cas particulier : Utilisation de procédures internes avec des fonctions asynchrones
Les procédures internes peuvent être utilisées comme "Callback" pour des fonctions asynchrones.
ATTENTION : Dans ce cas, le code situé après l'appel de la fonction utilisant une procédure WLangage asynchrone sera exécuté AVANT le code de la procédure Interne.
Exemple : Dans cet exemple pour WINDEV Mobile, le code situé après la fonction AlbumSélecteur sera exécuté AVANT la procédure interne. La procédure interne sera appelée lorsque l'utilisateur aura validé le sélecteur.
AlbumSélecteur(albumImage, SélectionPhoto)
PROCÉDURE INTERNE SélectionPhoto(sCheminImage)
	IMG_ChampImage = sCheminImage
FIN
// Code exécuté après la fonction AlbumSélecteur mais 
// AVANT le code de la procédure interne.
Limitations
  • Une procédure interne ne peut pas avoir le même nom que la ou les procédures qui la contiennent.
  • Deux procédures internes de même niveau ne peuvent pas avoir le même nom, même si elles sont déclarées dans des blocs de code différents (SI ALORS SINON, ...).
  • Les procédures internes ne sont pas disponibles en compilation dynamique.
  • Il n'est pas possible d'automatiser l'exécution d'une procédure interne.
  • La gestion automatique des erreurs n'est pas disponible sur les procédures internes.
  • Java Si l'option "Portée des variables locales limitée au bloc courant" est activée dans l'onglet "Compilation" de la description du projet, la déclaration de procédures internes utilisant des variables "avec limitation de portée" entraînera une erreur de génération. Exemple :
    • le code suivant provoque une erreur de compilation :
      PROCÉDURE MaProcedure()
      SI MaCondition ALORS
          str est une chaîne // str n'existe que dans la portée de l'instruction SI 
          PROCÉDURE INTERNE ma_proc_interne()
              str = "truc" // -> Fera une erreur à la génération Java/Android
          FIN
      FIN
    • Pour corriger ce code, il est nécessaire de ne pas déclarer la variable dans l'instruction SI :
      PROCÉDURE MaProcedure()
      str est une chaîne 
      SI MaCondition ALORS
          PROCÉDURE INTERNE ma_proc_interne()
              str = "truc"
          FIN
      FIN
    En Java et Android, il est recommandé de toujours déclarer les procédures internes dans la portée de la procédure elle-même. Ainsi, si des variables non déclarées sont utilisées, des erreurs de compilation seront affichées.
Version minimum requise
  • Version 20
Documentation également disponible pour…
Commentaires
Cliquez sur [Ajouter] pour publier un commentaire

Dernière modification : 18/09/2024

Signaler une erreur ou faire une suggestion | Aide en ligne locale