La programmation
Le WLangage
Le langage de programmation utilisé avec WINDEV est le WLangage commun aux autres logiciels de PC SOFT. Ce langage dit « de 5e génération » (L5G) permet à la fois la programmation procédurale et la programmation orientée objet (POO).
Le code créé se situe dans les événements du projet et de ses éléments constitutifs ainsi que dans des procédures ou dans des classes. Son écriture peut être en français (le plus courant) ou en anglais.
Le WLangage s’appuie sur les structures algorithmiques classiques incluant les séquences, les conditions et les répétitions.
Les fonctions proposées sont regroupées par familles. Le début de leur nom est basé généralement sur le nom de leur famille pour en faciliter la recherche et la mémorisation.
L’éditeur de code
Le code est écrit avec l’éditeur de code qui présente les événements disponibles pour l’élément en cours. Rarement modifiées, les Options de l’éditeur de code sont personnalisables à partir de l’icône Options de l’onglet Accueil du ruban.
L’icône dont l’infobulle est Code dans l’onglet Accueil du ruban fournit l’accès au code du projet ou de l’élément...
L’accès aux codes sources
Le Code du projet est accessible par l’icône Code de l’onglet Accueil du ruban.
Trois événements y sont disponibles :
-
L’Initialisation.
-
La Fermeture.
-
La Fermeture de session.
Le code spécifié dans l’Initialisation du projet est le code exécuté dès son lancement. Il est exécuté une seule fois. Les variables ou les constantes globales pour l’ensemble du projet doivent y être déclarées.
Le code indiqué dans la Fermeture est le dernier à être exécuté, et celui en Fermeture de session s’y substitue et s’exécute quand l’utilisateur ferme sa session Windows, alors que l’application est en cours d’exécution.
Dans le cas d’une fenêtre, son code est disponible par un clic droit sur le fond de la fenêtre suivi de l’option Code. Après un simple clic sur le fond d’une fenêtre pour la sélectionner, la touche [F2] ouvre aussi l’éditeur de code, de même que l’icône Code de l’onglet Modification disponible dans le ruban.
Cinq événements sont proposés :
-
Les Déclarations globales.
-
La Fin d’initialisation.
-
La Demande de mise à jour de l’affichage.
-
La Fermeture de la fenêtre fille.
-
La Fermeture de la fenêtre....
L’aide lors de la programmation
De nombreux aides et assistants sont fournis lors de l’écriture du code pour retrouver facilement les fonctions ou les instructions à utiliser, les écrire avec la bonne syntaxe, en connaître rapidement le résultat et les paramètres possibles.
Durant l’écriture du code, une liste s’affiche pour proposer de sélectionner la fonction, l’instruction ou l’élément du code ou du projet correspondant aux premiers caractères déjà écrits. C’est la complétion automatique.
Il est alors possible de continuer l’écriture, ce qui réduit petit à petit les propositions disponibles dans la liste, ou de sélectionner un élément par un clic ou avec les flèches du clavier. Les éléments se terminant par trois points ... regroupent les fonctions d’une même famille et permettent d’y accéder.
Des propositions sont aussi affichées pour les instructions qui sont complétées automatiquement lors de leur écriture.
L’instruction SI ALORS est complétée sans le saisir d’un FIN, de même que les instructions TANTQUE, POUR TOUT ou BOUCLE. Les imbrications entre instructions en sont facilitées. Le positionnement du curseur sur une instruction surligne sa structure pour en permettre facilement la lecture.
Les paramètres possibles pour une fonction sont proposés dès que la parenthèse pour la saisie des paramètres est tapée après le nom de la fonction.
Les paramètres sont...
Les variables simples et constantes
Une variable est l’allocation d’une partie de la mémoire vive de l’ordinateur pour y stocker une information. Elle est identifiée dans le code par son nom choisi librement par le développeur. L’information conservée en mémoire par une variable reste modifiable. La création d’une variable est nommée "déclaration de la variable". La déclaration est réalisable dans tous les codes. Le nom de la variable ne doit pas comporter de caractères spéciaux ou d’espace mais accepte les accents.
1. Déclaration
Pour être utilisée, une variable doit être déclarée. Son typage peut être explicite ou dynamique.
Dans le cas d’un typage explicite, la déclaration est écrite dans le code et sa syntaxe est composée de trois parties :
-
Son nom utilisé dans le code ou les champs pour y faire référence.
-
Le verbe "être" conjugué à la troisième personne est, sont suivi de façon facultative du mot un, une ou des.
-
Le type de la variable : entier, réel, chaîne, booléen, numérique, monétaire, buffer, dateheure, date, heure, durée, variant.
nom_utilisateur est une chaîne
chiffre_affaire est un monétaire
// similaire à
nom_utilisateur est chaîne
chiffre_affaire est monétaire
Le nom identifiant la variable doit être unique dans le code où elle est déclarée. Si une variable du même nom y existe ou est déjà déclarée comme globale, la déclaration affichera une erreur ou une information.
Des précisions de taille ou de format peuvent complémenter certains types pour les adapter aux informations à conserver en mémoire.
nom_utilisateur est une chaîne sur 30
chiffre_affaire est un numérique(6,2)
Les caractéristiques principales des variables de types simples sont les suivantes :
-
Les entiers sont des nombres sans partie décimale...
Les structures, variables composées et tableaux
1. Structures
Une structure est un type de variable qui regroupe des variables appelées "membres". La déclaration d’un membre au sein de la structure s’écrit de façon identique à celle d’une variable. La structure ne déclare pas de variable mais représente un type composé de variables.
La déclaration d’une variable du type de la structure est nécessaire pour l’utiliser. Plusieurs variables sont déclarables avec ce type.
La déclaration comprend deux parties principales :
-
Le nom de la structure suivi des termes est une structure.
-
Les membres au sein de la structure.
Le terme FIN termine la déclaration.
entreprise_str est une Structure
raison_sociale est une chaîne
adresse est une chaîne
chiffre_affaire est un monétaire
date_creation est une Date
FIN
// déclaration de deux variables utilisant la même structure
entreprise_paris est une entreprise_str
entreprise_limoges est une entreprise_str
La lecture ou la modification d’un membre se fait en indiquant le nom de la variable structurée suivi d’un point puis du nom du membre. Une liste des membres est proposée lors de l’écriture de la variable lorsque le point est tapé.
// entreprise 1 ...
Les opérateurs de comparaison et les opérateurs logiques
Opérateurs de comparaison
Un opérateur de comparaison compare deux valeurs et en retourne un résultat booléen Vrai ou Faux. Les valeurs comparées peuvent provenir de variables ou de fonctions. Le résultat d’une comparaison peut être affecté à une variable booléenne ou inclus dans des instructions conditionnelles ou répétitives pour définir leurs comportements.
Le symbole mathématique = (égal) retourne Vrai si deux valeurs sont strictement identiques. La combinaison de symboles ~= (tilde égal) entre deux chaînes est plus tolérante car elle ne tient pas compte des majuscules et des minuscules, des accents et des espaces en début ou en fin de chaîne.
Une comparaison peut être entourée de parenthèses pour l’isoler vis-à-vis d’autres comparaisons lors de l’utilisation d’opérateurs logiques ou pour une meilleure lisibilité.
resultat est un booléen
resultat = 1 > 2 // resultat = faux
c1, c2 sont des chaînes = ("Aldébaran","Capella")
resultat = ( c1 ~= c2 ) // resultat = faux
c2 = "ALDEBARAN" ...
Les instructions
1. Instructions conditionnelles
Une instruction conditionnelle définit les actions qui seront réalisées si certaines conditions sont réunies.
L’instruction conditionnelle s’écrit avec le terme SI suivi de la condition booléenne à respecter et du terme ALORS. Elle peut être sur une seule ligne s’il n’y a qu’une seule action à réaliser ou sur plusieurs lignes pour plusieurs actions. Sur plusieurs lignes, elle se termine par le mot FIN.
i est un entier = 5
SI i < 20 ALORS ToastAffiche("inférieur à 20")
// écriture similaire à
SI i < 20 ALORS
ToastAffiche("inférieur à 20")
FIN
i est un entier = 5
SI i < 20 ALORS
ToastAffiche("i est inférieure à 20")
i = i + 20
ToastAffiche("i plus 20 vaut "+i)
FIN
L’alternative précise les actions réalisées si les conditions sont réunies ou à l’inverse si elles ne le sont pas. Le mot SINON sépare les actions proposées par l’alternative. Comme pour l’instruction conditionnelle, elle peut s’écrire sur une ou plusieurs lignes.
i est un entier = 5
SI i < 20 ALORS Info("< à 20") SINON Info(">= à 20")
// écriture similaire à
SI i < 20 ALORS
ToastAffiche("< à 20")
SINON
ToastAffiche(">= à 20")
FIN
Comme toutes les instructions, elles peuvent s’imbriquer entre elles.
taille_s, taille_m, taille_l sont des entiers
taille_personnage est un entier = 150
SI taille_personnage <= 110 ALORS
taille_s += 1 // on ajoute une taille à S
SINON
SI taille_personnage...
Les mots réservés
Le nom d’un élément utilisé dans les codes permet d’en lire ou d’en modifier la valeur et fournit un accès à ses propriétés. L’usage de mots réservés rend le code indépendant de l’élément tout en permettant d’y faire référence.
Le terme MoiMême utilisé dans les codes désigne l’élément en cours. L’accès à ses propriétés se fait de la même façon que sur le nom du champ en ajoutant un ou deux points successifs après MoiMême.
MoiMême..Libellé = "Valeur du libellé"
En cas de copier-coller d’un champ, la référence MoiMême permet de ne pas changer le code lié au champ dupliqué.
Dans une fenêtre ou un état, les mots réservés MaFenêtre ou MonEtat sont associés à la fenêtre ou à l’état en cours et sont utilisables dans l’ensemble de leurs codes incluant ceux de leurs champs.
MaFenêtre..Largeur = 450
MaFenêtre..X = 100
MaFenêtre..ValeurRenvoyée = -1
Le mot réservé MonChampPopup fait référence au champ qui a ouvert la fenêtre popup comme par exemple un champ Combo. Ses propriétés ..ValeurAffichée...
Les procédures
Une procédure est un code réutilisable dont l’exécution peut être demandée à partir d’autres codes.
Les procédures locales sont propres à la fenêtre ou à l’état dans lequel elles sont créées. Elles ne sont utilisables que dans celui-ci. Les procédures globales sont regroupées dans des collections de procédures et sont utilisables dans tous les codes du projet.
Une fois l’éditeur de code ouvert, la création d’une procédure est réalisable grâce à un clic sur l’icône Nouveau de l’onglet Code du ruban, puis en choisissant entre une procédure globale ou locale.
Le volet Code permet lui aussi de créer des procédures en sélectionnant sur la droite l’élément en cours ou une collection de procédures, puis en exécutant un clic droit sur la partie gauche listant les procédures ou en cliquant sur l’icône affichant l’infobulle Créer une procédure locale.
La création d’une procédure locale ouvre la fenêtre suivante qui définit son nom utilisable pour y faire appel dans les autres codes. Ce nom est librement choisi par le développeur.
Si la case Générer un commentaire d’en-tête est cochée, des lignes de commentaires à compléter seront créées avant le code de la procédure. Ces lignes peuvent être retirées ou remises facilement en cliquant sur l’icône en forme de barres parallèles // en haut à droite du code. Il est possible de désactiver tout ou partie de ces commentaires dans les options de l’éditeur de code (accessibles par l’onglet Accueil du ruban).
Une procédure locale créée avec une visibilité publique est accessible depuis d’autres codes du projet si la fenêtre qui la contient est en cours d’exécution. Une procédure globale est toutefois à privilégier pour partager une procédure entre fenêtres. Avec une visibilité privée, une procédure locale n’est accessible que dans sa fenêtre.
Un rôle est attribuable à la procédure entre du code...
Échanger des variables entre fenêtres
À l’instar des procédures, des paramètres peuvent être transmis aux fenêtres lors de leur ouverture.
La première ligne du code de Déclarations globales d’une fenêtre commence automatiquement par PROCÉDURE MaFenêtre(). Aucun paramètre n’est indiqué par défaut entre les parenthèses.
Pour ajouter des paramètres qui seront à renseigner lors de l’appel de la fenêtre, la syntaxe est similaire à celle utilisée pour les procédures. Les paramètres sont spécifiés entre les parenthèses et séparés par une virgule.
Comme pour une procédure, le typage des paramètres est facultatif, quoi que conseillé.
// la fenêtre attend un paramètre obligatoire puis un optionnel
PROCÉDURE MaFenêtre(param_IDCLIENT est un entier, param_VILLE est
une chaîne = "")
Les paramètres déclarés correspondent à des variables globales de la fenêtre et sont utilisables dans tous ses codes et ceux de ses champs ou procédures locales.
Des valeurs peuvent être transmises à la fenêtre par des variables globales au projet, mais en gérant la fenêtre grâce à ses paramètres, celle-ci est indépendante vis-à-vis...
Fonctions WLangage
Le WLangage dispose de très nombreuses fonctions regroupées en familles.
Une fonction est soit écrite directement, soit écrite à la suite de la variable ou de l’élément sur lequel elle s’applique. Cette seconde méthode d’écriture se nomme la syntaxe préfixée.
// syntaxe classique
TableAffiche(TABLE_Client,taCourantBandeau)
// syntaxe préfixée similaire
TABLE_Client.Affiche(taCourantBandeau)
La saisie d’une fonction puis l’appui sur la touche [F1] lorsque le curseur est sur cette fonction ouvrent sa page d’aide pour lire ses syntaxes et ses options complètes.
Voici à suivre quelques unes des fonctions à connaître.
Gestion des fenêtres
-
Les fonctions Ouvre(), OuvreSoeur() et OuvreFille() ouvrent les fenêtres à l’inverse de la fonction Ferme(). La fonction FenEtat() indique ou change l’état d’une fenêtre.
-
Dans une fenêtre, la fonction RepriseSaisie() interrompt l’exécution du code en cours et replace le curseur sur le champ qui y est indiqué.
Gestion des données
-
La fonction HCréationSiInexistant() ouvre l’accès à un ou plusieurs fichiers décrits dans l’analyse. Si un fichier n’existe pas sur le disque dur, il est créé. La fonction HFerme() réalise l’inverse et en ferme donc l’accès.
-
La fonction HLitRecherche() recherche un enregistrement dans un fichier et met à jour le contexte HFSQL avec l’enregistrement trouvé. Elle peut être complétée d’une fonction HTrouve() validant que la recherche a fonctionné. Après avoir appliqué des modifications à un enregistrement, sa mise à jour dans la base de données est effective en utilisant la fonction HModifie().
-
La fonction HRAZ() initialise le contexte HFSQL d’un fichier avec ses valeurs par défaut définies dans l’analyse. L’attribut ..NouvelEnregistrement du fichier prend la valeur Vrai.
-
La fonction HAjoute() crée un enregistrement dans la base de données à partir des valeurs présentes dans le contexte HFSQL du fichier.
-
L’ajout ou la modification d’un enregistrement est aussi réalisable avec...
La programmation orientée objet (POO)
La création puis l’utilisation de classes pour créer une application correspond à la programmation orientée objet. Une classe modélise une partie de l’application pour définir certaines de ses données manipulées et les procédures qui interagissent avec elles.
La création d’une classe est réalisable par un clic droit sur Classes dans le volet Explorateur de projet puis en sélectionnant l’option Créer une classe, ou par la troisième icône du volet Code et son option Nouvelle classe.
La génération du Diagramme de classes du modèle UML (Unified Modeling Language) crée aussi les classes qui y sont décrites.
Une classe se veut autonome et transposable facilement d’une application à une autre. Ses données se nomment des "membres" et ses procédures des "méthodes".
Elle peut hériter d’une autre classe et en reprend alors les membres et les méthodes. Cela permet, dans la nouvelle classe dite "dérivée", de compléter les membres et les méthodes avec d’autres qui lui sont propres. Les modifications apportées à la classe d’origine dite "de base" ou "ancêtre" se répercutent automatiquement sur celles qui en ont hérité. L’imbrication des classes améliore alors la maintenabilité de l’application.
L’accès à un membre peut être plus ou moins limité. Par défaut, un membre est PUBLIC même si cela n’est pas explicitement indiqué dans sa déclaration. Il est utilisable par les codes du projet, de sa classe et des classes qui en héritent. En indiquant le terme PROTÉGÉ, il n’est utilisable que dans sa classe et les classes qui en héritent. Un membre PRIVÉ n’est utilisable que dans sa classe et invisible pour les autres classes et le projet.
L’utilisation des méthodes est également limitable selon la même logique. Une méthode PUBLIQUE est utilisable dans tous les codes. Une RESTREINTE n’est utilisable que dans sa classe et ses classes dérivées et une PRIVÉE...
La gestion des erreurs et des exceptions
1. Gestion automatique
Une erreur est le résultat d’une fonction du WLangage qui indique une anomalie non traitée mais non bloquante pour l’application.
// Exemple d'une erreur
fichier_txt est une chaîne
fichier_txt = fChargeTexte("C:\fichier_inexistant.txt")
// le fichier n'existant pas, la fonction fChargeTexte
// crée une erreur non bloquante. Le code, suite à cette
// erreur, continuera à s'exécuter
Info("Fichier traité.")
// Affiche "Fichier traité." malgré l'erreur
Le code, suite à l’erreur, est exécuté sans en tenir compte.
Une exception est une anomalie de programmation qui apparaît lors de l’exécution de l’application.
// Exemple d'une exception
// affichage du résultat d'une division par zéro
i est un réel = 1 / 0
Info( "Division par zéro = "+i )
// crée une exception
Cette anomalie arrête l’application tout en s’affichant. L’utilisateur peut en lire Plus de détails techniques et la Signaler aux développeurs.
Pour pallier les erreurs et les exceptions, chaque code dispose dans son en-tête des boutons Si Erreur : par programme et Quand Exception :...
Les indirections {}
Une indirection fait dynamiquement référence à un élément du projet, à une variable, à un champ ou une rubrique d’un fichier à partir de son nom fourni dans une chaîne de caractères. Elle s’écrit en indiquant le nom de l’élément concerné entre guillemets et entre accolades {}.
{"SAI_date",indChamp} = "20230108"
Le typage facultatif de l’indirection améliore son interprétation et se mentionne après le nom de l’élément séparé par une virgule. L’accès aux propriétés de l’élément se fait en ajoutant deux points successifs après l’accolade fermante suivis du nom de la propriété.
PROCÉDURE proc_fenetre_titre(LOCAL fenetre_nom est une chaîne,...
LOCAL fenetre_alias est une chaîne,...
LOCAL fenetre_titre est une chaîne)
{fenetre_nom,indFenêtre}..Alias = fenetre_alias
{fenetre_nom,indFenêtre}..Titre = "Mon Appli / "+fenetre_titre
Le nom de l’élément utilisé dans l’indirection correspondant à une chaîne de caractères, le compilateur ne le vérifie pas durant la création des codes et ne vérifie...
Le débogueur
Pendant la création de l’application, il est possible de l’exécuter ou d’en exécuter des parties réduites comme une fenêtre, un état ou une procédure pour en vérifier le bon fonctionnement.
L’option Déboguer le projet, disponible via l’icône Mode test de l’onglet Projet du ruban exécute l’application en lançant sa première fenêtre. Si cette dernière n’est pas encore définie, le lancement du test demandera à la définir. De même, les touches [Ctrl][F9] ou l’icône Go de l’accès rapide en haut à gauche et dont l’infobulle est Lancer le test du projet lancent, elles aussi, ce test d’ensemble.
Pour ne tester qu’une fenêtre, une requête partagée, un état ou une procédure, l’icône Go plus réduite dans l’accès rapide et dont l’infobulle commence par Tester lance le test sur l’élément ouvert. Dans le volet Explorateur de projet, ce test peut aussi être lancé par un clic droit sur une fenêtre ou un état suivi de l’option Tester. Bien que ce test ne concerne que l’élément en cours, les codes de Déclaration des Collections de procédures et d’Initialisation du projet sont exécutés.
Lors de ces tests, le logiciel WINDEV s’icônise dans la barre des tâches de Windows et l’application se lance comme pour un utilisateur lambda.
La fermeture de toutes les fenêtres de l’application permet de revenir à WINDEV. De même, un clic sur l’icône de WINDEV dans la barre des tâches ouvre WINDEV tout en laissant l’application lancée. Dans ce cas, l’icône carrée Terminer le test de l’onglet Débogueur du ruban arrête l’application.
Certaines informations techniques peuvent être affichées en parallèle de l’application en incluant dans les codes la fonction Trace() avec les informations voulues. La fonction Trace() ouvre une fenêtre indépendante de l’application pour y afficher les informations.
POUR i = 1 À 5
Trace("valeur de i = "+i) ...
Analyser les performances de son application
Des statistiques de performances sont récupérables durant l’exécution de l’application en mode test. Un clic sur l’icône Audit et performance et sur l’option Analyser les performances de l’onglet Projet du ruban lance l’application en mode test et affiche, lorsque celle-ci se termine, une étude détaillée des temps de traitement sur les codes exécutés.
Pour afficher les statistiques voulues, il est nécessaire de faire, dans l’application en mode test, les manipulations à observer.
La Synthèse présente un graphe et un tableau mettant en évidence les traitements les plus longs pour le thread observé qui est sélectionnable dans une liste déroulante. La Cartographie met aussi cela en évidence mais en représentant les durées par des surfaces. Le Détail montre toutes les opérations avec leurs durées, ce qui permet une analyse plus complète.
Un double clic sur la cartographie ou les fonctions indiquées dans les tableaux de la synthèse ou du détail en montre les Appels.
Pour une fonction en cours, les fonctions appelées et appelantes sont listées. Le bouton Code ouvre l’éditeur de code sur la fonction sélectionnée. Le bouton Début montre la première fonction...
Lire et écrire dans la base de données
1. Avec le WLangage
Les fichiers et leurs informations contenues dans les bases de données décrites dans l’analyse sont manipulables par programmation avec les fonctions HAjoute(), HModifie(), HEnregistre() et HSupprime().
Une application HFSQL a, par défaut, un unique contexte HFSQL qui représente en mémoire les enregistrements en cours de chaque fichier décrit dans l’analyse.
Ajouter une information
Pour ajouter une information dans un fichier, il faut effectuer les actions suivantes :
Vider le contexte HFSQL grâce à la fonction HRAZ(). La propriété ..NouvelEnregistrement du fichier concerné prend alors la valeur Vrai.
Renseigner les valeurs du contexte HFSQL soit par programmation en indiquant pour chaque rubrique du fichier une valeur, soit en utilisant la fonction EcranVersFichier() si les rubriques sont liées aux champs d’une fenêtre (onglet Liaison des champs).
Lancer la fonction HAjoute().
HRAZ(client)
// modifie les valeurs dans le contexte HFSQL
client.Nom = SAI_nom
client.Prenom = SAI_prenom
// similaire à
// uniquement si les champs sont liés aux rubriques
// (onglet Liaison des champs)
// EcranVersFichier()
// ajoute dans la base de données
SI HAjoute(client) ALORS
ToastAffiche("Client enregistré.")
SINON
Info(HErreurInfo(hErrComplet))
FIN
Lire une information
Pour lire une information dans la base, il convient de procéder ainsi :
Se positionner dans la base de données sur l’information à récupérer en utilisant la fonction HLitRecherche() sur une clé unique. Cette fonction recherche un enregistrement dans un fichier et renseigne le contexte HFSQL du fichier avec les valeurs de ses rubriques. Le contexte HFSQL du fichier contient alors son enregistrement en cours.
Afficher ou utiliser les informations présentes dans le contexte HFSQL. La restitution des informations dans une fenêtre se fait soit en écrivant dans le code une affectation de chaque rubrique aux champs concernés, soit en utilisant la fonction FichierVersEcran() si les rubriques...