Windows apporte pour tous les champs des comportements standard pour lesquels aucune programation n'est requise, et c'est tant mieux par ce que je ne programmerai pas tout ça tous les jours !
Mais comme il est toujours bon d'en vouloir plus, on peut dans certain cas ne pas vouloir du comportement standard sur une action bien précise. Par exemple, on pourrait décider qu'un champ ascenseur ne doit pas réagir à la roulette de la souris. Il suffit pour y parvenir d'ajouter le traitement optionnel "roulette souris", puis de faire renvoyer la valeur "0" à l'événement Windows correspondant (cf. montage écran).
En effet, le traitement optionnel est appelé lorsque Windows fait l'envoi de l'événement au champ, et avant même que Windows n'ait effectué son action standard. De ce fait on peut très bien exécuter un code avant l'action standard de Windows, et aller jusqu'à l'inhiber comme dans ces exemples.
Cela est également valable avec la fonction "Evénement" du WLangage qui fonctionne suivant le même principe.
28 novembre 2006
Inhiber une action standard sur un événement (clavier, souris...)
Publié par Elian Lacroix 0 commentaires
Rubriques associées au billet : Interface / Ergonomie, Programmation
27 novembre 2006
Imprimer directement depuis un aperçu...
La fenêtre d'aperçu propose lors de l'impression de choisir le nombre de pages à imprimer, ainsi que le nombre de copies. D'un point de vue ergonomique, cela peut ne pas convenir à certains usages, voici la méthode pour ne pas avoir de confirmation et imprimer directement :
Aperçu personnalisé :
Il faut tout d'abord copier dans le répertoire du projet la fenêtre de l'aperçu, c'est une fenêtre WINDEV dans le répertoire des exemples. Ouvrir ensuite cette fenêtre dans le projet, afin de l'enregistrer dans les éléments du projet. Par le menu "Projet / Description du projet" et le volet "Style", il faut donner cette fenêtre comme fenêtre d'aperçu. A ce stade, il est possible de personnaliser la fenêtre utilisée lors de l'aperçu depuis l'application.
Modification de l'aperçu :
Ouvrir la description du bouton "Imprimer", et simplement changer son nom en "ImprimerTout". Au prochaine aperçu, ce bouton lancera directement l'impression !
Publié par Elian Lacroix 0 commentaires
Rubriques associées au billet : Impressions, Interface / Ergonomie
23 novembre 2006
Big Brother dans les applications ...
Dans un site en exploitation avec des données en perpétuelle mouvements, il n'est pas rare de rencontrer deux utilisateurs se disputant la propriété ... d'une erreur de manipulation.
- C'est toi il y a une semaine qui m'a dit de rentrer la nouvelle adresse.
- Oui mais ensuite je l'ai changée à nouveau, tu n'aurais pas du l'écraser !
- Non je ne l'ai pas changée à nouveau, c'est toi qui a oublié de la changer ...
Au final le conflit est stoppé en se tournant vers l'informaticien en charge du programme :
- [en coeur] : on vient te voir car l'application a encore perdu une adresse.
Ca sent le vécu pour beaucoup j'en suis certain. Un remède très efficace existe, c'est la journalisation. Cerise sur le gâteau, son activation se fait par une case à cocher dans la description des fichiers de l'analyse, aucune programmation n'est requise. La journalisation des écritures est suffisante pour régler tout litige tel que décrit ci-dessus.

- la date de l'heure de modification,
- la valeur,
- le poste depuis lequel le changement a été fait,
- le login de l'utilisateur qui a fait le changement.
Toutes ces informations peuvent également être proposées par une interface spécifique de l'application, avec la fonction "HHistoriqueModification" qui retourne, entre autre, toutes ces informations sur les modifications.
Plus de doute sur qui a fait quoi !
Autre intérêt, la journalisation permet après une restauration de données de rajouter à la sauvegarde les dernières modifications.
Deux recommandations pour l'utilisation de la journalisation :
- utiliser dans le programme la fonction "HPoste" pour renseigner le journal précisément sur l'auteur des changements,
- placer les journaux sur un autre disque que celui contenant les données, avec la fonction "HChangeRepJNL".
Publié par Elian Lacroix 0 commentaires
Rubriques associées au billet : Hyper File / Base de données, Interface / Ergonomie, Programmation
22 novembre 2006
Mémorisation de la position des colonnes de table inopérante ?
Option à ne pas oublier dans la description des tables : mémoriser la position des colonnes. Elle permet sans ajouter de code, de proposer à l'utilisateur final de toujours retrouver les colonnes comme il les a lui-même positionnées.
Seulement il peut arriver que cette mémorisation soit inefficace sur une table donnée, sans raison apparente. Il y a bien sûr une explication : la propriété "..MenuContextuel". En effet, l'affectation de la propriété "..MenuContextuel" d'une table, inhibe la restauration de ses paramètres mémorisés. Ceci dans le but de ne pas avoir de colonne invisible, qui ne pourrait pas être restaurée. Mais encore faut-il le savoir, je n'ai pas trouvé l'information dans la documentation. Je l'ai obtenue du support après avoir cherché un long moment pourquoi dans une même fenêtre une première table avait ses colonnes bien remises en place, mais pas une seconde.
Peut-être qu'une prochaine version de WINDEV pourra afficher des informations aux développeurs pour les informer lors de l'utilisation d'une propriété de ce type des effets engendrés sur d'autres fonctions.
Publié par Elian Lacroix 0 commentaires
Rubriques associées au billet : Interface / Ergonomie, Programmation
17 novembre 2006
Fichier en cours d'utilisation ... mais par qui ?
Un fichier de données reste parfois ouvert, alors que l'on est persuadé qu'il n'est plus utilisé, et que tous les programmes l'utilisant sont arrêtés...
Fichier en cours d'utilisation sur un autre poste ...
Le fichier est utilisé par un autre processus ...
Un utilitaire pouvant se substituer au gestionnaire de tâches est très commode, car il permet de connaître les processus qui utilisent un fichier. Il s'agit de Process Explorer, à toujours garder dans ses outils de travail. Anecdote, l'éditeur d'origine est Sysinternal, mais il semble qu'il y ait eu récemment une absorption de Microsoft. En effet, l'adresse http://www.sysinternals.com est directement redirigée sur un site Microsoft !

Au passage, deux "pièges" pouvant aboutit à laisser un fichier de données ouvert ...
- fichier Hyper File, appeler la fonction "HFerme", mais oublier les "HAnnuleDéclaration" sur les requêtes exécutées sur ce même fichier,
- fichier externe : appeler "fCrée" et "fOuvre", et ne faire qu'un seul "fFerme". Pour éviter tout risque d'erreur, préférer "fOuvre" seule, mais avec le paramètre "foCréation".
Une image (celle du site Microsoft) de l'utilitaire complet, tel qu'il apparaît si vous le substituez au gestionnaire de tâches :

Publié par Elian Lacroix 3 commentaires
Rubriques associées au billet : Généralités, Hyper File / Base de données
15 novembre 2006
Importer un fichier texte dans un fichier Hyper File en formatant des dates
L'importation d'un fichier texte dans un fichier Hyper File est facilitée par la commande "HImporteTexte". Dans le cas favorable, l'importation est donc extrêmement simple grâce à cette fonction. Bien évidemment, suivant l'origine des données à importer, on se trouve en dehors du "cas favorable", il suffit par exemple qu'une date n'ait pas le format "AAAAMMJJ" attendu.
Dans ce cas, il faut avoir recours à une bonne vieille moulinette, facilitée par l'instruction POUR TOUT.
L'exemple ci-dessous utilise une demande du forum, ce sujet revenant assez régulièrement d'ou l'idée de ce billet. Il faut souligner qu'il s'applique aux dates, mais également à tout ce qui peut nécessiter une conversion avant la mise en base.
Soit un fichier texte à importer avec le contenu suivant (une tabulation sépare les colonnes, un retour chariot sépare les lignes ) :
15/03/2002 abc imo 560,33
19/04/2003 klo hap 561,00
12/06/2001 dol pme 7840,00
Si la date dans le fichier texte avait été codée sous la forme "20020315" la fonction "HImporteTexte" aurait fait l'affaire. Mais avec ce codage de date, il faut mouliner (une fois de plus ?). Voici un exemple de code pouvant être utilisé :
sEnregistrementsAImporter est une chaîne
sNouvelEnreg est une chaîne
sDateNonformatée est une chaîne
sEnregistrementsAImporter = fChargeTexte("C:\MonFichier.txt")
POUR TOUTE CHAINE sNouvelEnreg DE sEnregistrementsAImporter SEPAREE PAR RC
sDateNonformatée = ExtraitChaîne(sNouvelEnreg, 1, TAB)
Fichier.Date = ChaîneVersDate(sDateNonformatée, "JJ/MM/AAAA")
Fichier.Personne = ExtraitChaîne(sNouvelEnreg, 2, TAB)
Fichier.Libellé = ExtraitChaîne(sNouvelEnreg, 3, TAB)
Fichier.Montant = ExtraitChaîne(sNouvelEnreg, 4, TAB)
HAjoute(Fichier)
FIN
Une bonne évolution de la fonction "HImporteTexte", serait de pouvoir donner dans les délimiteurs un format de date comme le prend la fonction "ChaîneVersDate". Le champ d'action de "HImporteTexte" serait grandement étendu. J'en ai fait la suggestion au support.
Publié par Elian Lacroix 4 commentaires
Rubriques associées au billet : Hyper File / Base de données, Programmation
14 novembre 2006
Une option de menu contextuel en gras
Une astuce permet de passer une unique option d'un menu contextuel, ayant le look XP, en gras.
Il suffit d'intervenir sur le libellé, et de l'encadrer avec les balises HTML de mise en gras, l'image ci-contre met en évidence ce procédé.
Cela permet par exemple de mettre en évidence l'option la plus couramment utilisée, un "petit plus" dans une interface !
Publié par Elian Lacroix 0 commentaires
Rubriques associées au billet : Interface / Ergonomie
10 novembre 2006
Bêta Blogger avant WINDEV 11, pour une leçon d'ergonomie !
En attendant de pouvoir m'initier aux nouveautés de WINDEV 11, je découvre la bêta version des Blogs façon Google. Un sacré chamboulement puisqu'en terme de fonctionnalités, visibles tout autour de ce billet, il est maintenant possible :
- d'ajouter des flux RSS,
- de regrouper les billets par sujets,
- d'avoir une arborescence des archives ...
Mais surtout, et là chapeau, surtout il est possible d'obtenir tout cela sans aucune programmation Web, dans un environnement totalement dynamique. Un simple glisser/déplacer d'un élémement dans la page permet de disposer les différentes zones du blog. Un modèle d'ergonomie.J'encourage tous ceux qui le peuvent à prendre quelques minutes pour créer un blog de test, juste pour découvrir la simplicité avec laquelle toutes les possibilités du blog sont proposées. Les développeurs se sont réellement creusés pour parvenir à un tel résultat, c'est un très bel exemple de respect de l'utlisateur.
Publié par Elian Lacroix 0 commentaires
Rubriques associées au billet : Inclassable / Hors sujet, Interface / Ergonomie
Stockage des images, optimisation de l'espace en changeant le format...
Une rubrique mémo image est généralement affectée par une commande de la forme Fichier.RubriqueImage = ChampImage, ou "EcranVersFichier".
Cette affectation copie fidèlement l'image contenue dans le champ, au format BMP.
En fonction du contenu de l'image, un enregistrement en JPEG est souvent suffisant en qualité, et permet de diviser la taille de l'image par un facture important. Il suffit pour cela d'affecter la rubrique avec un appel de la fonction "dSauveimageJPEG" :
Fichier.RubriqueImage = dSauveImageJPEG(ChampImage, enMémoire)
Petite astuce bien utile s'il faut gagner un peu de place, surtout si l'application doit à un moment donné transférer ces images.
Publié par Elian Lacroix 0 commentaires
Rubriques associées au billet : Hyper File / Base de données, Programmation
09 novembre 2006
Présentation par défaut de l'interface d'une application déployée
L'utilisateur final d'une application peut configurer la présentation de son application :
- position et taille des fenêtres,
- largeur des colonnes des tables,
- mémorisation de valeurs pour les champs...
Comme il est courant pour tout le monde de changer d'avis, il est souhaitable de lui proposer une option de l'application permettant de revenir à l'état initial pour toutes les informations mémorisées. Il peut s'agit d'un menu "Paramètres / Rétablir l'affichage par défaut". Cette option devra simplement faire la suppression dans la base de registres de la clé retournée par la fonction "ProjetInfo(piRegistre)".
Pour aller plus loin sur ce mécanisme, il est également possible de remplacer la sauvegarde faite dans la base de registres, par une sauvegarde dans un fichier XML. Cette possibilité est donnée par la fonction "InitParamètre". L'avantage est alors de pouvoir facilement "transporter" les paramètres sauvegardés d'un poste à un autre. Il est même envisageable de conserver le fichier XML dans un fichier de la base de données, afin de le restituer automatiquement au lancement de l'application en fonction de l'utilisateur qui se connecte !
Publié par Elian Lacroix 0 commentaires
Rubriques associées au billet : Interface / Ergonomie
08 novembre 2006
Loupe de recherche des colonnes des tables
Voici une "checklist" à appliquer lorsque la loupe d'une colonne de table fichier n'apparaît pas lors de l'exécution.
- la coche "Avec recherche (loupe)" doit être active dans la description de la colonne, tout comme la coche "Triable" (volet "Général"),
- la rubrique du fichier associé à la colonne (volet "Liaison") doit être une clé dans le fichier (unique ou doublon peut importe),
- le remplissage de la table doit se faire sans programmation. Il s'agit du sélecteur "Parcours automatique" dans la description de la table (volet "Contenu"),
- l'option "Ascenseur proportionnel" doit également être cochée toujours dans la description de la table (volet "Détail").
Toutes ces conditions doivent être réunies dans le cas d'une table directement reliée à un fichier. Si la table est reliée à une requête, la nécessité de clé dans le fichier de données disparaît.
Publié par Elian Lacroix 0 commentaires
Rubriques associées au billet : Interface / Ergonomie
03 novembre 2006
Accélérateur de traitement ...
Avec son nom tout à fait anodin, la propriété "..AffichageActif" peut accélérer de façon considérables des traitements. En effet, vous pouvez l'observer avec l'analyseur de performances, les accès à l'interface sont coûteux temps. Par exemple un parcours de données avec des "TableAjoute" dans une table mémoire (champ d'affichage) sera plus long qu'un même parcours chargeant une variable tableau (fonction "TableauAjoute"). Là peut intervenir avantageusement la propriété, en inhibant provisoirement l'affichage. Exemple :
NomFenêtre..AffichageActif = Faux
TraitementXYZ()
NomFenêtre..AffichageActif = Vrai
Simple, mais redoutable d'efficacité dans bien des cas de figure !
Publié par Elian Lacroix 1 commentaires
Rubriques associées au billet : Programmation
02 novembre 2006
Etat imprimé à tout faire (zone répétée, variable tableau...)
Par défaut l'assistant de création des états permet de sélectionner des données dans les fichiers de l'analyse, une requête, un champ table...
Il existe une méthode d'impression "passe partout" car elle permet d'imprimer tout aussi facilement tout et n'importe quoi. L'idée de ce billet m'est venue en voyant le forum, pour l'impression des données d'une zone répétée.
Il suffit dans l'assistant de création d'état d'indiquer "Je programme la lecture de ma source de données", puis de créer dans l'état des champs avec les types et masques désirés. C'est le code de l'état et du bloc corps que se chargeront du parcours des données, la programmation est minime :
// code d'ouverture de l'état
// Déclaration d'une globale pour parcourir les répétitions
// ou pourquoi pas les éléments d'une variable tableau...
gnIndice est un entier = 1
// Code de lecture des données de l'état
// Termine l'impression si toutes les répétitions ont été vues
SI gnIndice > ZoneRépétéeOccurrence(FEN_FenetreAppelante.ZR_ZoneRépétée1) ALORS
RENVOYER Faux
SINON
RENVOYER Vrai
FIN
// Code avant impression du bloc corps
// Affectation des champs de l'état avec les attributs
// de la zone qui permettent d'avoir les valeurs
RUB_RUBRIQUE1 = FEN_FenetreAppelant.ZR_ZoneRépétée1.ATT_Attribut1[gnIndice]
RUB_RUBRIQUE2 = FEN_FenetreAppelant.ZR_ZoneRépétée1.ATT_Attribut2[gnIndice]
RUB_RUBRIQUE3 = FEN_FenetreAppelant.ZR_ZoneRépétée1.ATT_Attribut3[gnIndice]
...
// Incrémentation du compteur pour passer à la prochaine répétition.
gnIndice++
Cette méthode peut être étendue à tout ce qui peut se parcourir, dans l'exemple on lit les répétitions d'une zone répétée, mais il peut s'agit d'un tableau, d'une zone mémoire, un fichier texte...
Publié par Elian Lacroix 1 commentaires
Rubriques associées au billet : Programmation
Représentation binaire d'une valeur.
A toute fin utile, voici un traitement proposé en réponse sur le forum pour obtenir la représentation binaire d'une valeur. La fonction de conversion inverse est donnée également.
FONCTION VersBinaire(nValeurDecimal)
sBinaire est une chaîne = ""
nb est un entier = nValeurDecimal
TANTQUE nb > 0
SI modulo(nb,2) ALORS
sBinaire = "1" + sBinaire
SINON
sBinaire = "0" + sBinaire
FIN
nb = nb/2
FIN
RENVOYER sBinaire
Et la récupération d'une valeur exprimée en décimal, à partir de sa représentation binaire :
FONCTION DepuisBinaire(schaineBinaire)
sBinaire est une chaîne = schaineBinaire
i est un entier
j est un entier
nDecimal est un entier
nCalcul est un entier
POUR i = Taille (sBinaire) A 1 PAS -1
nCalcul = 2*Val (sBinaire[[i A i]])
SI nCalcul ALORS
nDecimal += Puissance (nCalcul,j)
FIN
j++
FIN
RENVOYER nDecimal
Publié par Elian Lacroix 0 commentaires
Rubriques associées au billet : Programmation