SAUVEGARDEZ LES SETTINGS DE VOS FORM EN UNE LIGNE DE CODE !

violent_ken Messages postés 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 - 20 nov. 2006 à 19:59
mimiZanzan Messages postés 301 Date d'inscription lundi 27 février 2006 Statut Membre Dernière intervention 17 décembre 2017 - 6 déc. 2006 à 02:23
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/40398-sauvegardez-les-settings-de-vos-form-en-une-ligne-de-code

mimiZanzan Messages postés 301 Date d'inscription lundi 27 février 2006 Statut Membre Dernière intervention 17 décembre 2017
6 déc. 2006 à 02:23
Pour conserver l'utilisation éventuelle du tag pour certains contrôles, je propose une petite astuce:
-mettre un séparateur (par ex "/") entre la préférence et le tag normal désiré pour le ctle.
-utiliser les fonctions suivantes pour récupérer la préférence et le tag normal:

Private Function TagPref(ByVal Ob As Control) As String
'donne la préférence écrite dans le tag
Dim k As Integer
k = InStr(Ob.Tag, "/")
TagPref = Left(Ob.Tag, k - 1)
End Function

Private Function TagCtl(ByVal Ob As Control) As String
'donne le tag à utiliser pour le contrôle
Dim k As Integer
k = InStr(Ob.Tag, "/")
'cas contrôle sans pref"
If k 0 Then TagCtl Obj.Tag: Exit Function
TagCtl = Right(Ob.Tag, Len(Ob.Tag) - k)
End Function

Il suffit donc par ex de remplacer Obj.Tag par TagPref(obj)dans les Sub GetFormSettings et SaveFormSettings de la classe.
Si on a besoin du tag d'un contrôle, on appelle TagCtl(obj).
C'est tout simple!
violent_ken Messages postés 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 2
24 nov. 2006 à 18:52
Certes, je sais que le Tag n'est pas conçu uniquement pour faire tourner ma source.

Cependant, la non-utilisation de cette méthode restreint les possibilités de l'utiliateur quant au choix des propriétés/composants à sauvegarder.


Je vais essayer de repenser à çà, mais j'ai plusieurs codes en parallère en ce moment ^^
@+
bouv Messages postés 1411 Date d'inscription mercredi 6 août 2003 Statut Membre Dernière intervention 3 mars 2019 1
24 nov. 2006 à 08:09
"utiliser le tag est parfois très (trop?) fastidieux."

Je rajouterai que cette méthode peut parfois poser problème. J'avais par exemple fait un petit code qui stockait la position et taille des controles dans leur TAG. Ceci afin qu'ils soient redimensionnés automatiquement quand on redim la form. On ne pourra donc pas faire tourner nos deux code en même temps.
Je parle également pour moi, mais il est préférable (autant que faire ce peut) d'utiliser une autre méthode pour stocker ce type d'infos.
violent_ken Messages postés 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 2
22 nov. 2006 à 13:54
bouv ==> exact, j'ai oublié de changer le "obj" pour la form dans mon copier/coller...

Pour le choix des propriétés à sauvegarder, je vais réfléchir à un système simple de gestion à partir du tag.

Merci pour la note !

PCPT ==> En fait, le premier code posté ne ressemblait pas à ce qu'il est maintenant... donc j'ai recherché si le code initial existait déjà, mais j'ai pas cherché sur vbfrance si la mise à jour que j'ai postée ressemblait à quelque chose de déjà existant... et apparement, le même genre de truc a déjà été fait (par toi)
Je vais regarder ta source plus détail ce soir, avec mon PC.

Si tu demandes ce que ma source apporte de plus, je suppose alors que la réponse est "la même chose que la tienne" ^^
J'ai regardé rapidement le source du *.ctl, çà ressemble énormément en effet :

For Each oCtrl In oFrm
If TypeOf oCtrl Is TextBox Then...

"utiliser le tag est parfois très (trop?) fastidieux." ==> certes, mais çà permet de pouvoir sélectionner les controles à sauvegarder ou non, et de sélectionner les propriétés à sauver ou non (voir dernière remarque de bouv).

"ps : et si la Txtbox est en "*"" ==> Ah euh oui, j'ai pas pensé à ce cas là... sauver un mdp dans un fichier ini si le dev oublie de ne pas remplir le tag est très facheux ^^ je changerais ce détail


Merci pour les commentaires, @+
PCPT Messages postés 13272 Date d'inscription lundi 13 décembre 2004 Statut Membre Dernière intervention 3 février 2018 47
22 nov. 2006 à 00:53
salut,
j'ai regardé en diagonale seulement...
ok tu gères pas mal de contrôles mais... quel plus apporte ton code à celui-ci?
http://www.vbfrance.com/codes/ENREGISTRER-APPLIQUER-PARAMETRES-FORM-LIGNES-CTL_35970.aspx
(un peu de promo ok ^^)


utiliser le tag est parfois très (trop?) fastidieux.
par contre de mémoire, mon code ne gère pas les groupes de contrôle

ps : et si la Txtbox est en "*" ?? (le dev DOIT ne pas remplir le tag?)
code propre en tout cas.
++ ;)
bouv Messages postés 1411 Date d'inscription mercredi 6 août 2003 Statut Membre Dernière intervention 3 mars 2019 1
21 nov. 2006 à 23:33
Hum c'est bien mieux ainsi.
Juste une petite erreur :

If Left$(LCase$(Obj.Tag), 4) = "pref" Then
'ici, il faut aussi gérer les propriété de la form en elle même

a remplacer par
If Left$(LCase$(Frm.Tag), 4) = "pref" Then

Par ailleurs il aurait pu etre bien de choisir les propriétés que l'on souhaite enregistrer.

Par exemple pour un Slider je peux vouloir sauvegarder les propriétés Min, Max mais pas Value.

Dans ce cas dans le tag on peut par exemple mettre "pref|1|1|0" ou quelque chose du genre.

Sinon c'est du bon boulot.
Je peux désormais noter
10/10.

J'attends quand même la mise à jour pour le choix des propriétés ^^
violent_ken Messages postés 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 2
21 nov. 2006 à 20:27
Bon voilà, le nouveau code est complètement différent...

C'est ULTRA simple désormais !

@+
violent_ken Messages postés 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 2
21 nov. 2006 à 19:43
J'ai une idée, je vais voir si çà abouti...

@+
violent_ken Messages postés 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 2
21 nov. 2006 à 19:10
"En fait je m'explique sur "je n'ai pas le sentiment que cela simplifie vraiment la gestion des .ini"

C'est juste que quoi qu'il arrive on est obligé d'ajouter une ligne par parametre à l'ouverture du logiciel et une ligne à la fermeture. Cela comme avec une gestion manuelle."

> Certes, je me suis mal exprimé.
Le processus est le même pour l'ajout de paramètres à sauvegarder.

Le gain de temps si situe dans le cas ou l'on lit les valeurs sauvegardées plusieurs fois dans le programme ; pas plusieurs appels à la procedure LireIni, mais juste un à la classe.
Simplification aussi dans le mode de récupération de ces valeurs, on les récupère plus simplement grâce à la classe (pas de grosses déclarations publiques, et c'est plus explicite de faire text=Preferences.PathParDefaut...)

Pour la fonction IsFileCreated, elle est mieux, mais inutile car l'API créé elle même le fichier si inexistant ^^


Pour ce que tu proposes, c'est très intéressant, mais il faudrait pouvoir aussi récupérer des valeurs de variables (pas seulement des property de composants).


Je vais voir ce que je fais.
Merci encore, @+
bouv Messages postés 1411 Date d'inscription mercredi 6 août 2003 Statut Membre Dernière intervention 3 mars 2019 1
21 nov. 2006 à 15:46
Oui effectivement mes 2 fonctions sont très semblables aux tiennes.
Juste le nom change ^^

La fonction IsFileCreated est mieux ainsi.

En fait je m'explique sur "je n'ai pas le sentiment que cela simplifie vraiment la gestion des .ini"

C'est juste que quoi qu'il arrive on est obligé d'ajouter une ligne par parametre à l'ouverture du logiciel et une ligne à la fermeture. Cela comme avec une gestion manuelle.

Je te donne un petit axe de travail si tu souhaites réellement simplifier la gestion des parametres d'une appli.

L'idée serait la classe sache dans quelle propriété de quel objet lire et ecrire les données.

Dans ta classe, un truc du genre :
With Prerefenres
.Section1_Var1 = PropertyAdress(MaForm.Caption)
.Section1_Var2 = PropertyAdress(MaForm.Height)
.Section1_Var3 = PropertyAdress(MaForm.Top)
End With

A l'ouverture de l'appli uniquement :
With Prerefenres
.IniFilePath = CheminDuIni
.Load
End With

A la fermeture de l'appli uniquement :
With Prerefenres
.Save
End With

On peut même imaginer une procédure du type

Public Sub PropertyAdd (Section as String, Cle as String, Property as ???)
violent_ken Messages postés 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 2
21 nov. 2006 à 13:58
Salut,

Je reprend dans l'ordre les remarques :
1) "Quel est l'interet de "créé le fichier par défaut" lorsqu'il n'existe pas ?
Dans ce cas de figure GetPrivateProfileString et WritePrivateProfileString gèrent très bien la situation.
GetPrivateProfileString retourne une chaine vide et WritePrivateProfileString créé le fichier, créé la section, créé la clé et enregistre la variable." ==> Je n'étais pas au courant que WritePrivateProfileString gèrait cela... çà va effectivement largement simplifier le tout.

2) "- Quand tu utilise GetPrivateProfileString : pour la variable lpDefault utise vbNullString plutôt que """ ==> Certes.

3) "- Pour la fonction IsFileCreated regarde dans les codes de EBArt ou Renfield. Il me semble que l'un d'eux a pondu un code un peu plus propre un jour." ==> lol ;) La fonction que j'ai postée est assez lamentable ;) Il faudra évidemment que je change çà (sans doute une procedure codée en 2s pour pouvoir tester la classe, et je n'ai pas changé la procédure par la suite).
Ceci devrait être plus propre (pas testé, masi sans doute correct):

Public Function IsFileCreated(sFile as String) As Boolean
Dim WDF as WIN32_DATA_FIND 'ou un type dans ce genre, mais peu importe le contenu
Dim hFile as Long

hFile=FindFirstFile(sFile,WDF) 'API utilisée pour vérifier que le handle est valide
FileExists=(hFile<>INVALID_HANDLE_VALUE) 'constante = -1

FindClose hFile 'ferme le handle ouvert
End Function


3) Pour tes deux procedures, elle sont relativement proches de ce que j'ai fait (tout à fait logique d'ailleurs), mais
strReturn String(255, 0)> String$
Left(...) ==> Left$
Chr(0) ==> VbNullChar
devrait optimiser (certes c'est très léger) la vitesse d'exécution.

L'intérêt de ne pas gérer directement ces procédures dans le code (module ou form) mais dans une classe permet d'éviter à rajouter des appels à ces procédures si l'on désire ajouter des variables dans le fichier *.ini en cours de codage de l'application...
Aussi, on appelle la classe une fois au loading du programme, une fois pour sauvegarder les perfs dans la form de configuration, et c'est tout.
Donc deux lignes de code pour stocker/charger toutes ses préférences.
Le type perso définit par la seconde classe permet de pouvoir gérer plus facilement l'obtention des valeurs des variables (ex, loading d'un form, on fait commondialog1.initdir=Preferences.DefaultPath_OpenFile, plus simple que faire GetIniFile(Default_Path,...)


4) Pour l'utilité du code... c'est en effet peu évident à première vue.
Disons que l'intérêt existe :

-quand le nombre de paramètre à sauvegarder est important (50-100)

-dans la mesure ou le type de donnée de la Variables "Preferences" (la classe clsIniPref) permet de transporter toutes les préférences, et donc de faciliter la sauvegarde des paramètres dans le programme (par exemple le bouton 'Apppliquer' de la form de configuration ==> on ne passe que la variable Preferences enn paramètre) et leur lecture (appel unique à la classe en sub de démarrage, et récupération des infos dans la variable Preferences publiques dans tout le programme).
Quel intérêt par rapport à un type perso ? Le type perso nécessite des procédures publiques dans un module (Function LireIni(byval sfile as string) as TYPE_PREFERENCE et Sub EcrireIni(byval pref as TYPE_PREFERENCE)).
Donc type perso+module ou classe, autant avoir une classe.

> Donc évidemment, pour la sauvegarde de 5 paramètres, utiliser deux classes comme je le propose est douteux. Mais dans le cas d'une grande application avec un nombre important de variables à sauver, je pense que c'est une méthode plus pratique.
En fait, je m'attendais à ce type de remarque concernant l'intérêt de la source ;)




Donc pour conclure :
-ma fontion de test de présence de fichier est lamentable, ce n'est qu'un oubli de la "phase debug"
-création de fichier *.ini par défaut gérée par l'API, je savais pas et j'en suis très content ==> va simplifier le bazard
-intérêt surtout pour un grand nombre de paramètres à sauver


Merci pour ces remarques constructives, je mettrais à jour ce soir quand je retrouverais mon PC.
@+
bouv Messages postés 1411 Date d'inscription mercredi 6 août 2003 Statut Membre Dernière intervention 3 mars 2019 1
21 nov. 2006 à 13:04
Bon ok il y a un petit travail de reflexnion derriere tout ça mais je n'ai pas le sentiment que cela simplifie vraiment la gestion des .ini
Mais sur ce point chacun en dira ce qu'il veut.

Pour entrer danbs la critique :

- Quel est l'interet de "créé le fichier par défaut" lorsqu'il n'existe pas ?
Dans ce cas de figure GetPrivateProfileString et WritePrivateProfileString gèrent très bien la situation.
GetPrivateProfileString retourne une chaine vide et WritePrivateProfileString créé le fichier, créé la section, créé la clé et enregistre la variable.

- Quand tu utilise GetPrivateProfileString : pour la variable lpDefault utise vbNullString plutôt que ""

- Pour la fonction IsFileCreated regarde dans les codes de EBArt ou Renfield. Il me semble que l'un d'eux a pondu un code un peu plus propre un jour.


Perso j'utilise directement les fonction suivantes :

Public Function EcritDansFichierIni(Section As String, Cle As String, Valeur As String, FichierIni As String) As Long
EcritDansFichierIni = WritePrivateProfileString(Section, Cle, Valeur, FichierIni)
End Function

Public Function LitDansFichierIni(Section As String, Cle As String, FichierIni As String, Optional ValeurParDefaut As String = vbNullString) As String
Dim strReturn As String
strReturn = String(255, 0)
Call GetPrivateProfileString(Section, Cle, ValeurParDefaut, strReturn, Len(strReturn), FichierIni)
LitDansFichierIni = Left(strReturn, InStr(strReturn, Chr(0)) - 1)
End Function

Bonne prog
++
violent_ken Messages postés 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 2
20 nov. 2006 à 19:59
Postez votre avis et votre note ;)
@+
Rejoignez-nous