La FAQ Visual Basic 6.0 [FAQ VB] - Divers - Programmation
Marsh Posté le 12-03-2003 à 19:41:09
Niquel, ca marche, je te dirai demain si cela marche aussi sur les postes ou l'erreur ODBC 'unknown table in WHERE clause' se fait sur VB ...
Merci
Marsh Posté le 12-03-2003 à 19:42:21
Je voudrais également en savoir plus sur la fonction oCon.Open :
que renvoie-t-elle en cas d'erreur ? (si elle renvoie quelque chose ..)
Marsh Posté le 12-03-2003 à 19:43:38
Drasche > je n'ai pas eu de GPF, c'est normal ?
Marsh Posté le 12-03-2003 à 19:43:43
ça génère une erreur vb mais avec un message venant d'ADO. Tout dépend de la nature de l'erreur
Marsh Posté le 12-03-2003 à 19:45:26
drasche a écrit : ça génère une erreur vb mais avec un message venant d'ADO. Tout dépend de la nature de l'erreur |
Ouais j'ai bien vu ca ... mais j'aimerai bien traiter l'erreur en interne en fait
Paske sinon, si le client fait n'importe quoi avec les outils mis a disposition, ben *PAF*
Marsh Posté le 12-03-2003 à 19:46:58
Skylight a écrit : Harkonnen > pour un modo, c'est une sale blague |
on peut pas être bon tout le temps
Marsh Posté le 12-03-2003 à 19:49:25
Skylight a écrit : On peut néanmoins être plus bon que mauvais |
un peu de sérieux svp, sinon je ferme le tomic !
et d'ailleurs,
Marsh Posté le 12-03-2003 à 20:13:09
Skylight a écrit : Ouais j'ai bien vu ca ... mais j'aimerai bien traiter l'erreur en interne en fait |
ben là c pas compliqué, tu dois la traiter comme n'importe quelle erreur VB. Pour plus de détails, il te faudra consulter la doc à propos d'ADO
Marsh Posté le 12-03-2003 à 20:16:25
Bon je vais relire mon MSDN ... pfiouu c dur de reprendre le VB
Marsh Posté le 13-03-2003 à 20:55:11
J'ai une question...
comment recuperer le code d'erreur de la ligne qui se connecte ?
par exemple :
' Initialisation de la connection
Set oCon = New Connection
Call oCon.Open(strConnect)
ben j'aimerais (j'ai fait un on error .... avant) recuperer le resultat .. comment ?
Marsh Posté le 13-03-2003 à 21:10:58
manière classique:
Code :
|
Marsh Posté le 24-03-2003 à 11:47:12
Comment avoir des icônes dans la traybar?
La traybar est cette barre d'icônes que vous trouvez à côté de l'horloge sur le bureau de Windows. Le but de ce post est de vous montrer comment en disposer facilement pour votre application. Comme malheureusement beaucoup de techniques avancées, Visual Basic 6 fait usage de l'API Win32 pour arriver à ses fins.
En premier lieu, vous devez placer ces déclarations dans un module:
Code :
|
Déclarer la variable suivante dans une form:
Code :
|
Initialisation de "nid" dans la form: dans l'exemple suivant, je lui donne l'icône de la form pour mettre dans la traybar, puis un tooltip équivalent au titre de la form.
Code :
|
Comment ajouter l'icône à la traybar:
Code :
|
Comment détruire l'icône de la traybar:
Code :
|
Marsh Posté le 24-03-2003 à 12:40:11
Juste une précision à partir de la connection à une base de donnée, ou instanciation de n'importe quel objet.
J'ai eu le problème avec une appli VB qui ne devait pas être accompagnée de la moindre DLL, mais juste afficher des instructions si un composant n'était pas présent, ou faire sans s'il n'était pas critique.
Lorsqu'on lie un composant via le menu "référence" dans VB, il y a plusieurs avantages, dont voici les principaux :
- VB reconnait l'objet lorsqu'on tape son nom, ce qui est très pratique pour écrire un programme lorsqu'on ne sans pas exactement comment l'utiliser.
- Lorsqu'on va générer le package de déploiement, il va automatiquement inclure les DLL nécessaires.
- L'éxécution du programme va être plus rapide, car la création des objets est déja "câblée", et les espaces réservés aux objets à la bonne taille.
Mais un problème de très grosse taille :
- Si une des DLL nécessaires au projet n'est pas référencée, on obtient un plantage non trappable, cela ne fait pas pro du tout.
Donc, une solution, relativement gourmande en ressources (tout est relatif) est donc de ne pas lier ces objets au niveau du projet, mais dynamiquement dans le code au moment où on en a besoin.
J'ai fait ça pour MSXML, ADO et MAPI j'ai eu de très bons résultats, ce qui permet, dans une application qui n'a pas forcément le besoin vital de toutes ces bibliothèques, de griser les fonctions faisant appel à ces fonctions.
Dans mon cas, j'avais besoin de faire un petit client VB qui devait récupérer des commandes au format XML depuis la boîte aux lettres du client, ou un fichier plat depuis un serveur WEB.
L'utilisateur pouvait ensuite modifier les informations depuis une interface dans le programme, ou directement en ligne avec une page XSL, puis devait renvoyer les informations modifiées, soit en connection directe à une base, soit par mail, soit par FTP.
La multiplication des moyens de recevoir les informations et de les renvoyer était là pour pallier aux lacunes de certaines DLL sur les postes clients.
La première version, avec des objets liés directement dans le projet faisait des erreurs fatales lors de l'accès à certaines fonctions lorsque certains composant n'étaient pas présent.
Pour pallier au problème, j'ai donc dû utiliser l'astuce du "createobject".
Voici un exemple :
Code :
|
Voilà, ce code fonctionne même si aucune librairie ADO n'est installée, ce qui permet donc de verrouiller des fonctions non vitales au programme, sans pour autant planter.
Marsh Posté le 24-03-2003 à 13:27:31
Oui, la méthode par référencement est dite "Early binding" et la méthode avec les CreateObject s'appelle "Late Binding". Toutefois il y a une différence en termes de performances: l'early binding dispose directement de toutes les informations COM nécessaires à la compilation, alors qu'en late binding, c'est à l'exécution que cela se passe.
Faut voir évidemment les contextes d'emploi de chacune de ces deux écoles, mais perso, je préfère le early binding.
Par contre, je ne suis pas d'accord quand tu dis que l'erreur est non trapable
Je viens de faire un test: j'ai repris le projet du premier post en rajoutant une gestion d'erreur, puis l'ai compilé. Ensuite, je me suis débarrassé des DLL ADO (malgré le système de protection de Win2K ) et j'ai relancé le programme: l'erreur est bien trappée par moi et non par le système, exactement de la même manière qu'avec CreateObject. A ce niveau, il n'y a pas de différence entre les deux: ou l'objet est créé, ou il n'est pas créé.
Marsh Posté le 24-03-2003 à 15:04:50
Je trouve ça bizarre, tu dois toujours avoir des trucs dans le BDR ou je ne sais quoi.
Car quand la référence est manquante, l'erreur se produit au moment du "dim", hors les erreurs de dim ne sont pas trappable. Ou alors ta gestion d'erreurs est une gestion que je ne connais pas, et ça m'intéresse grandement.
Comment tu fais ça ?
Marsh Posté le 24-03-2003 à 15:10:49
ben euh ya rien de compliqué, il suffit d'éviter les Dim machin as new truc et c'est dans la poche Bon je parle pour l'exécutable évidemment; dans l'IDE, je n'ai pas vraiment essayé, d'autant que j'ai le réflexe Ctrl-F5 contrairement à certains collègues qui n'ont toujours pas compris que l'usage du F5 seul n'amène que des ennuis
Juste une remarque -maintenant que j'y pense-, j'ai voulu le code du premier post le plus simple possible et sans se prendre la tête sur d'autres aspects de VB
Edit: et merci pour ta contribution
Marsh Posté le 25-03-2003 à 09:48:44
drasche a écrit : Comment avoir des icônes dans la traybar? |
J'ai testé et c'est super! mais j'ai quand même deux questions:
1 J'aimerai bien faire clignoter cette icone, c'est possible?
2 C'est surement très simple mais lorsque l'on clique sur l'icone, comment gérer pour effectuer une action?
Marsh Posté le 25-03-2003 à 10:25:31
1. jamais essayé, je dirais alterner ton icône avec une icône transparente sur base d'un timer ou quelque chose du genre (on peut modifier l'icône, préférable à une séquence effacement/ajout), grâce à l'argument lHM_NIM_MODIFY.
2. Il suffit d'intercepter l'évènement MouseMove de la form et de vérifier l'état des paramètres passés en arguments. Problème, c'est que je n'ai pas de moyen de vérifier si la souris agit sur la form elle même ou sur l'icône
Marsh Posté le 08-04-2003 à 09:11:29
J'y pense seulement maintenant: comment introduire des ressources custom dans un programme VB6.
http://forum.hardware.fr/forum2.ph [...] 664&cat=10
Marsh Posté le 15-04-2003 à 10:49:02
Moi ça ne marche pas cet exemple, avec le debuger, ça plante au niveau de "set oCon = New Connexion", est-ce que ça pourait venir du fait que je n'utilise pas Visual basic, mes une macro VBA Excel? Car dans reference, je n'ai pas "Visual Basic runtime objects and procedures" et "Visual basic object and proceure".
Comment faire?
Marsh Posté le 21-04-2003 à 20:30:28
drasche a écrit : 1. jamais essayé, je dirais alterner ton icône avec une icône transparente sur base d'un timer ou quelque chose du genre (on peut modifier l'icône, préférable à une séquence effacement/ajout), grâce à l'argument lHM_NIM_MODIFY. |
Pour le point 1, ça fonctionne très bien avec un timer
2: Enfin trouvé... Faut simplement utiliser une PictureBox, on utilise cette image comme icone et on utilise l'évènement mousemove de la PictureBox et non de la form...
Marsh Posté le 21-05-2003 à 14:44:45
Les tableaux (arrays)
Un ptit topic sur les tableaux (tableaux), ça peut aider
Il y a plein de façons d'utiliser les tableaux en VB, avec plus ou moins de limitations selon les cas. Je vais partir de l'exemple a priori le plus restrictif vers le moins restrictif.
Pour jouer avec les tableaux, quelques instructions à connaître:
IsArray(): la fonction prend une variable en paramètre et renvoie un booléen: tableau = true, pas tableau = false. Si c'est un tableau non dimensionné, c'est évidemment considéré comme un tableau.
LBound(): renvoie la borne inférieure de le tableau passé en paramètre. Si la variable n'est pas un tableau ou un tableau non-dimensionné, vous vous mangerez une erreur 9: subscript out of range.
UBound(): pareil que LBound mais renvoie la limite supérieure du tableau.
Array2Immediate(): fonction de mon cru qui affiche le contenu d'un tableau.
Cas 1: Les tableaux à taille fixe
Les tableaux à taille fixe sont dimensionnés lors de la déclaration et ce définitivement. Ils sont donc à ce titre les plus simples à utiliser.
La manière propre est de déclarer le tableau avec l'indice maximum. L'astuce est que contrairement au C, la déclaration suivante:
Code :
|
réserve non pas 5 mais 6 éléments indicés de 0 à 5 (0..n), alors qu'en C, ce serait de 0 à 4 éléments (0..n-1)
La manière malpropre serait un truc du genre:
Code :
|
qui réserve un tableau dont seuls les éléments de 2 à 5 existent réellement.
NB: ici le fait que les tableaux soient typés ou non n'a aucune importance, mais les limites valent surtout pour des tableaux typés.
Code :
|
Cas 2: les tableaux dynamiques
Ils se déclarent comme ceci:
Code :
|
NB: de nouveau, le type n'est pas spécifié ici mais la démonstration est valable pour un tableau typé
Dans ce cas, on peut dimensionner et redimensionner à tout va, en choisissant de préserver ou non les données, avec toutefois certaines limites que nous allons voir. Une instruction est disponible pour manipuler les tableaux dynamiques: Redim.
Redim est utilisé dans 2 contextes:
1) le contexte bourrin: on efface tout et on recommence. Dans ce cas:
Code :
|
va redimensionner le tableau à 6 éléments (de 0 à 5)
2) le contexte dynamique: on décide de changer la dimension du tableau (parce qu'on désire ajouter de nouveaux éléments):
Code :
|
En admettant qu'on reprenne la déclaration précédente, cette instruction en rajoute 1, sans altérer les éléments 0 à 5 qui sont déjà présents dans le tableau.
Code :
|
Cas 3: les splits
Les instructions Split et Join permettent de convertir des chaînes de caractères en tableaux et inversément, en spécifiant un séparateur pour préciser le ou les caractères qui vont jouer le rôle de séparateur de liste. L'instruction Split, qui renvoie un tableau, ne peut toutefois avoir une variable déclarée comme tableau en sortie. Il faut que ce soit un pur Variant.
Code :
|
Cas 4: les tableaux multidimensionnels
En VB, on peut sans problème créer et gérer des tableaux multidimensionnels, que ce soit de manière fixe ou dynamique. Toutefois, dans une gestion de tableau dynamique, seule la dernière dimension pourra être altérée. Il est cependant impératif que le tableau ne soit pas dimensionné à la déclaration, comme c'est le cas dans les exemples précédents. Certaines choses changent toutefois:
LBound et UBound demanderont un paramètre supplémentaire qui est le numéro de la dimension dont on veut connaître les bornes. Si je dis:
Code :
|
Alors:
Code :
|
renverra 4. Oui, les dimensions se comptent à partir de 1 jusqu'à n dimensions.
Code :
|
Cas 5: Les tableaux dans les tableaux
Etant donné qu'un tableau peut contenir des variants, il peut également contenir des tableaux lui-même, et pas forcément de mêmes dimensions, et pas forcément non plus du même nombre de dimensions
Rassurez vous, je vais rester avec des tableaux à une seule dimension pour rester clair
Code :
|
Et pour terminer (et pour l'exemple), voici la fonction Array2Immediate:
Code :
|
Marsh Posté le 04-07-2003 à 14:27:38
Généralités sur VB6/VBA (à compléter avec d'autres éléments plus tard)
Compilation/Interprétation
D'abord, il faut absolument remettre une vérité à sa place. Contrairement à ce que croient pas mal de gens (y compris des spécialistes), VB ne compile pas grand chose. Il se contente de vérifier que la syntaxe est bonne, mais il ira rarement vous dire un truc aussi commun que "Type mismatch" au moment de la compilation, alors qu'un autre compilateur ne vous ratera pas. L'exception portera notablement sur les arguments passés par référence. Bref, la plupart du vrai travail de compilation se fait pendant l'exécution, et c'est ce qu'on appelle de l'interprétation.
[Full Compile]
Réflexes à acquérir:
1) Option Explicit est une clause à mettre en tête de tous vos modules (dans les Options/Editor -> Require variables declarations), ceci vous obligera à déclarer toutes vos variables.
2) Typez vos variables! Ne laissez pas le type Variant vous pourrir la vie, évitez-le le plus souvent possible!
3) Quand vous lancez une application sous VB, faites toujours un Start with Full Compile (raccourci ctrl-F5 au lieu de F5). Ce qui vous évitera de vous faire charcuter par ceux qui ont le réflexe Full Compile une fois qu'ils récupéreront vos sources, et accessoirement de voir immédiatement certains bugs dans votre code.
Exemple simple: le casting
Parfois on fait des calculs impliquant des types différents. Quand on met des immediates, c'est encore pire, VB assigne un type à chacun, et fait des associations pour déterminer quel est le meilleur type dans une opération. Tout cela durant l'exécution bien entendu. On peut dire sans risque que l'algorithme en question n'est pas au point. Preuve en est avec ce simple code exécuté dans l'Immediate Window:
Code :
|
Cette ligne donnera un overflow. 24 est considéré comme un Byte, 3600 comme Integer et 68742 comme un Long. Qu'est-ce qui s'est passé? VB décompose le calcul en opérations élémentaires, et prend le type le plus fort des deux éléments. Il va donc tenter de multiplier 3600 par 24. 3600 est un Integer et 24 est un byte, il prend donc un Integer pour stocker le résultat. Mais 3600 * 24 = 86400 qui est trop gros pour être stocké dans un Integer. Donc, plantage. Le malheur est que même si vous aviez l'intention de stocker le résultat dans un Long, VB tentera tout de même de stocker le résultat dans un Integer. Le code suivant provoque un overflow sur la dernière ligne:
Code :
|
Ca m'amène à une remarque en particulier: il ne faut jamais assumer quoi que ce soit en programmation, et plus en VB qu'un autre langage. Assumer ou supposer. Même si le C par exemple, vous fera payer certaines de vos imprudences au prix fort (une bonne petite GPF histoire de vous traumatiser un coup, voire même planter complètement et irrémédiablement votre PC), VB est aussi capable du pire. Employez hasardeusement une API Windows (ce qui reviendra presque à faire du C) et je vous promets autant de problèmes qu'en programmant en C. VB, de par son caractère simple et son aspect RAD, est capable de vous ralentir et de vous causer des maux de têtes dès que vous grattez un peu. Il faut oublier tout ce que vous avez appris dans d'autres langages car vous ne pourrez pas l'appliquer à VB. VB est un langage à part, et avec un framework bien à lui, avec des limitations que vous ne rencontrerez pas sur d'autres plate-formes, et pour obtenir une implémentation qui fera exactement la même chose qu'un programme C, vous vous casserez plus la tête que si vous l'aviez fait directement en C!
VB ne se plaindra jamais d'un type mismatch alors qu'un compilateur C vous bloquera jusqu'à ce que la situation lui paraisse consistante. VB se plante dans l'exécution car il interprète, il ne compile pas (c'est d'ailleurs la meilleure preuve que VB n'est pas un compilateur). En conséquence de quoi, n'assumez jamais rien, mettez des castings explicites là où il en faut, suppléez aux carences de VB si nécessaire, et utilisez les API Windows!
Autre exemple: comparaison de strings (StrComp)
Le type String est le type le plus lent en VB. Il faut bien savoir que VB travaille en unicode, c'est à dire 2 bytes physiques par caractère. Chaque fois que vous faites une opération dessus, VB va faire plein de choses en background pour tester la string que vous lui soumettez. Parlons de la comparaison de strings.
Là, j'ai honte de le dire, mais bien qu'ayant sûrement aperçu la chose dans MSDN une fois ou l'autre, je n'ai jamais regardé de près. Il s'agit de la fonction StrComp. Cette fonction compare des strings 20x plus rapidement qu'un bête test 'string = string'. Pas la peine de se casser la tête si vous avez quelques malheureux caractères. Ce serait plutôt à employer sur des travaux intensifs sur de grosses strings.
Les propriétés par défaut
Nombre d'objets VB, voire tous, ont une propriété par défaut, qui sera invoquée rien qu'en spécifiant l'objet. L'interpréteur VB est capable de déterminer cette propriété au runtime. Ca veut dire qu'il use du temps machine 1) pour la retrouver et 2) pour déterminer son type. Autrement dit, n'utilisez pas cette feature, d'autant qu'en assumant sa propriété par défaut, vous risquez un bug, une confusion est très vite arrivée. Votre code n'en sera d'ailleurs que plus clair, même si certaines lignes seront plus longues.
Clause With
La clause With est un grand bien, spécialement pour les applications qui emploient une architecture avec des objets, collections et compagnie. L'objet With permet d'économiser de nombreux cycles machine sur des expressions du type: obj.collection.item(1).valeur, car l'adresse de .valeur est évaluée au runtime et à chaque fois qu'elle est spécifiée quelque part. Autrement dit, il va d'abord récupérer l'adresse d'obj, puis de collection, puis de la propriété item, laquelle va rechercher l'élément qui se cache derrière l'index 1, et enfin la propriété valeur. Tout ça au runtime. Par contre, si vous avez un simple objet dont vous voulez manipuler les propriétés, utiliser un With juste pour le plaisir d'avoir un code moins chargé ne sert absolument à rien. Le With n'a vraiment d'avantage à être employé que sur des collections d'objets (sur les objets eux-mêmes, pas les collections).
La sérialisation
Certaines personnes sont déroutées lorsqu'on leur apprend qu'un nom de fonction peut servir de variable, puisque VB impose de faire fonction = valeur pour spécifier la valeur de retour de cette fonction à la différence d'autres langages qui propoposent plutôt return valeur (y compris VB.NET). C'est ce qu'on appelle la sérialisation. Dans la fonction, le nom de la fonction-même peut être utilisé n'importe où comme identificateur du même type (bien entendu) de la fonction. Vous pouvez même relire la valeur et la modifier, exactement comme n'importe quelle variable. Toutefois, ce mécanisme n'empêche pas l'usage de la récursivité, c'est à dire que la fonction puisse s'appeler elle-même. VB saura très bien faire la différence entre une sérialisation et un appel récursif. Toutefois, les appels récursifs sont historiquement (et c'est toujours d'actualité) à déconseiller car ils font appel à la pile, de même que les variables locales à une fonction, et il convient d'en faire un usage économe. Notez que VB.NET, malgré l'introduction du mot-clé return, équivalent à celui du C, n'empêche pas la sérialisation.
Profiler: mesurer les performances
En ce qui concerne les tests de performance, utilisez un profiler, c'est un logiciel qui va chronométrer l'exécution de chaque ligne de code de votre application et vous en faire un rapport. Lorsqu'on a des problèmes de performances, c'est l'outil tout désigné pour trouver où votre application perd du temps.[#ff0000][/#ff0000]
Marsh Posté le 17-09-2003 à 15:56:58
Tables liées avec des recordset (SHAPE)
Aprés de longues recherches, j'ai trouvé comment lier des tables et les afficher dans des datagrid en passant par des recordset et sans utiliser de dataenvironment ni de controles ADO.
Code :
|
Voili voilou!
Marsh Posté le 17-09-2003 à 18:16:40
Merci
faudra que j'essaie ça une fois rentré au boulot
Marsh Posté le 17-09-2003 à 18:40:48
drasche a écrit : Merci |
ça fonctionne super et en plus on est pas limité à une arborescence à un seul niveau comme avec le DataEnvironment...
Marsh Posté le 01-10-2003 à 21:00:23
Merci drasche! franchement excellent
Marsh Posté le 02-10-2003 à 21:18:55
Une petite question en passant, Comment on peut gérer correctement les dates de VB avec une base Access? (Le mois est quelques fois remplacé par le jour...)
J'ai une soluce bancale pour le moment et c'est pas l'idéal!
Marsh Posté le 02-10-2003 à 21:28:10
tu peux essayer le format universel: année-mois-jour. C'est sans équivoque possible. Année à 4 chiffres bien sûr
Cependant je sais pas si Access le gère bien, tout SGBD devrait en principe.
Marsh Posté le 07-10-2003 à 14:42:55
Support des skins Windows XP
Le support des skins Windows XP par VB est pour ainsi dire inexistant, et surtout, ça n'a pas été étudié pour. Je vais faire un peu le tour de ce sujet et vous mettre en garde contre 2 ou 3 choses qui font que "ça ne marche pas toujours bien". J'ai personnellement développé une appli puis ajouté le support des skins Windows XP, et j'ai pu constater que ce n'était pas aussi simple que cela.
De manière générale, et pas seulement en VB, il suffit d'ajouter un manifest en tant que ressource dans votre projet, ou comme fichier externe dans le même répertoire que l'exécutable. Je vais répondre en fait à deux questions ici, comment faire pour que l'IDE (et tout ce qui tourne sous l'IDE) supporte les skins Windows XP, et comment faire pour que les applications compilées en fassent autant.
Comment faire pour que l'IDE supporte les skins Windows XP?
Visual Studio lui-même peut supporter les skins si on le lui demande. Pour ce faire, créez un fichier nommé vb6.exe.manifest dans le même répertoire que vb6.exe (typiquement C:\Program Files\Microsoft Visual Studio\VB98 si vous avez installé VB6 dans son répertoire par défaut), puis introduisez le code suivant dans ce fichier:
Code :
|
Sauvez le fichier, lancez VB6 (sous Windows XP), et voilà le support des skins acquis! Cela marchera également pour tout projet que vous lancez sous l'IDE, vous verrez alors rapidement les défauts surgir, pour peu que vos interfaces soient élaborées. Notez qu'il vaille mieux que ce fichier ait une taille équivalente à un multiple de 4. C'est biscornu mais il semble que ce détail ait parfois son importance. Je n'ai, quant à moi, pas remarqué de problème particulier.
Comment faire pour que les applications VB6 supportent les skins Windows XP?
Grosso modo, pareil que pour l'IDE. Mais ici, c'est vous qui tenez les sources, et vous pouvez inclure le manifest à l'exécutable en tant que ressource. Pour l'intégration de ressources, je vous renvoie au topic dédié.
Pour intégrer le manifest en tant que ressource, il faut intégrer le code suivant à votre fichier de ressources:
Code :
|
Ensuite, lors du démarrage de votre application, il vous faut lancer une procédure dédiée à cet usage. Le code à intégrer devrait ressembler à ceci:
Code :
|
Ce code permet d'initialiser l'application pour utiliser les skins Windows XP et il vous faudra appeler cette procédure au début de votre programme. Avec une interface de base, ce code n'est a priori pas nécessaire. Si vous utilisez des contrôles externes, je vous recommande de le faire.
Une fois tout cela fait, vous verrez un changement notable. Prenez une skin qui modifie sensiblement votre interface et vous verrez mieux, genre MacOS X.
Passons maintenant aux exceptions. Il est possible que votre interface ne soit pas 100% Windows XP compliant. Il est même possible que d'hideuses tâches noires soient apparues dans votre interface. Il y a 3 problèmes connus.
1) Le contrôle SSTab disponible dans les composants dans l'OCX "Microsoft Tabbed Dialog Control", lequel vous propose des onglets, ne supporte absolument pas le skinnage. Il vous faudra utiliser le TabStrip, disponible dans l'OCX "Microsoft Windows Common Controls 6.0". Si vous êtes familiers avec la programmation des treeview et listview, tous deux disponibles dans le même OCX, vous ne serez pas dépaysés, car les interfaces de programmation sont similaires.
2) Les boutons intégrant des bitmaps. Eux non plus n'aiment pas le skinning Windows XP. Je n'ai pas encore cherché de workaround, mais je l'exposerai ici dès que je l'aurai trouvé.
3) Les frames. Les frames ne disposant pas de handle de fenêtre, ils sont à peine considérés comme des contrôles et surtout, posent un problème au niveau du rafraichissement d'écran. Et le problème qui se pose ici est que tout contrôle disposé à l'intérieur d'un frame risque de ne pas du tout apparaître comme vous le souhaitiez. Cela s'applique notamment aux contrôles CommandButton, et OptionButton.
Pour l'exemple: la fenêtre d'origine:
Et la fenêtre skinnée sans aucun changement (thème MacOS X)
Comme vous pouvez le voir, leur "fond" est noir. Si vous espériez des formes arrondies pour votre bouton, vous aurez des coins carrés et noir à la place. Pour corriger ce problème, soit votre frame est invisible (j'entends par là pas de bordure ni de caption), et vous la remplacez par un PictureBox, lequel est capable d'assumer le rôle d'une frame, soit votre frame est bien visible et il vous faudra intercaler un PictureBox entre le frame et vos contrôles. Oui, c'est lourd, mais si vous voulez vraiment appliquer les skins à votre application, vous n'aurez pas d'autre choix. A noter que le PictureBox devra être plus petit que votre frame, sous peine de voir disparaître caption et bordures. Et cela implique de devoir repositionner tous vos contrôles dont le positionnement se fait par rapport au parent! J'ai voulu me lancer dans cette entreprise sur une application assez volumineuse, et j'ai rapidement laissé tomber, d'autant plus que le SSTab a été imposé au début du projet.
Voici de quoi à l'air la fenêtre avec un skin correct:
J'ai laissé la bordure du PictureBox visible mais dans la pratique, vous pouvez bien évidemment vous en rendre quitte.
Voilà, une fois que vous aurez appliqué tous ces points, votre application devrait se montrer sous les beaux apparats proposés par Windows XP.
Marsh Posté le 27-10-2003 à 13:26:16
Null et Empty
Ces deux valeurs sont particulières en VB et ne se manipulent pas n'importe comment.
Commençons avec le Null:
En VB6, un type numérique (Byte, Integer, Long, Single, Double, Currency), un objet (quelconque), une date (Date), un booléen (Boolean) ou une chaîne (String) ne peuvent avoir de valeur "null". Les valeurs par défaut sont toujours et respectivement de zéro, Nothing, "0:00:00" (on l'évalue avec l'expression CDate(0), False ou "" (chaîne vide).
Pour avoir le vrai Null, il faut que la variable soit du type Variant (un type plasticine inventé par M$ qui peut être n'importe quoi par nature; en .NET, ce sera le type Object).
Sur une variable d'un autre type que Variant, une tentative de lecture ou écriture de la valeur Null se soldera par une erreur: "Invalid use of Null" (usage invalide de Null).
Pour y remédier, et savoir si le Variant contient effectivement la valeur Null, on utilise la fonction IsNull, et on lui passe la variable en argument. Le Null est généralement rencontré dans les interfaces de programmation (API) liées aux bases de données, comme DAO, RDO et ADO.
La valeur Empty:
Une nouvelle fois, la valeur Empty ne peut être utilisée qu'avec le Variant, mais sa signification est différente. En effet, lorsque vous déclarez une variable de type Variant, celle-ci est de n'importe quel type, et elle n'est donc pas initialisée. Elle contient la valeur Empty.
Tout comme le Null, la valeur Empty ne peut être lue ou assignée sur un type standard, sauf le Variant, mais ne provoquera pas d'erreur, ce qui est beaucoup plus sournois: vous ne serez pas prévenu d'une manipulation incorrecte.
Marsh Posté le 27-10-2003 à 18:59:30
merci drasche
Marsh Posté le 28-10-2003 à 22:14:13
Pourquoi dit-on que VB ne gère pas les objets?
La question n'est pas exacte: VB gère les objets, mais ne les implémente pas. Il n'est pas possible de faire de la pure programmation objet comme on en ferait dans n'importe quel autre langage. Si vous voulez pratiquer la programmation objet, passez votre chemin, VB n'a pas été étudié pour ça. Et d'ailleurs, je me demande ce qui a bien pu passer dans la tête des gens qui ont conçu l'aspect objet dans VB.
Oui, bien sûr, vous disposez de classes grâce auxquelles vous pouvez créer des objets. Mais la programmation objet, ce n'est pas que cela. C'est aussi l'héritage, le polymorphisme et les patrons de classes (templates diront les habitués). Et ça, VB le fait mal (héritage, polymorphisme) ou pas du tout (templates).
Les classes
Voyons une classe tout à fait élémentaire:
Code :
|
Cette classe se contente de stocker une valeur. Pour les besoins de l'exemple, je ne me suis pas contenté de déclarer un Public Value As Long, ce qui d'un point de vue extérieur à la classe aurait donné exactement la même chose. Il s'agit plutôt de vous habituer tout de suite au concept de propriété.
Une propriété est une fonction déguisée pour lire ou écrire une valeur appartenant à une classe. Le préfixe "ppv" de ppvValue signifie d'ailleurs "private property value" ou valeur privée de la propriété.
Comme vous le voyez dans l'exemple, la déclaration d'une propriété se fait en double: un Let (écriture dans la propriété) et un Get (lecture de la valeur de la propriété). Il existe également le Set pour assigner un objet plutôt qu'un type standard. D'ailleurs, un objet se crée selon la syntaxe suivante:
Code :
|
et se détruit comme suit:
Code :
|
Le mot-clé New indique à VB que vous voulez instancier votre classe en mémoire. Et le mot-clé Nothing, que vous voulez le détruire.
Jetons un oeil vite fait à la manière dont VB gère la mémoire. Rien ne vous empêche d'avoir plusieurs références vers un seul et même objet. Il suffit de la recopier. Reprenons MonObjet, et pour une raison ou une autre, vous décidez qu'une autre variable va en recevoir la référence:
Code :
|
Voilà, rien de plus simple, j'ai copié l'adresse de mon objet vers une autre variable. L'identifiant ne dispose jamais que de l'adresse de votre objet, et à ce niveau, c'est tout ce que vous pouvez gérer. Si vous voulez recopier votre objet, il faudra le faire à la main, propriété par propriété, pour autant que l'interface de la classe que vous utilisez vous le permet.
Comment détruire un objet en VB?
En fait, il ne suffit pas simplement de mettre MonObjet à Nothing. Il faut s'assurer qu'aucune autre variable ne dispose de son adresse! Tant qu'une variable disposera de l'adresse de votre objet, celui-ci continuera à perdurer en mémoire. Démonstration:
Code :
|
Remarque: lorsque vous utilisez des collections pour stocker des objets, c'est pareil: la collection garde une référence vers l'objet, et tant que la collection existe, il existe au moins cette référence vers votre objet.
L'héritage
L'héritage permet par un moyen (normalement!) simple d'étendre l'interface de votre classe, tout en la réutilisant. Dans n'importe quel langage, la déclaration prend une ligne. En VB... ça dépend de votre interface.
Exemple d'un héritage à la VB de la classe écrite plus haut:
Code :
|
Un Option Explicit en haut de chaque module, quelque soit sa nature, est toujours de bon aloi, et recommandé pour éviter quelqu'ennui de compilation
Code :
|
Ceci est la ligne unique qu'on trouverait dans un autre langage et qui dit: je veux hériter de ClassAncetre.
Code :
|
C'est ici que les Romains s'empoignèrent... Vous devez déclarer, instancier puis détruire la classe dont vous héritez, en même temps que la vôtre.
Code :
|
Et là c'est la prise de tête. Nous avions donc une propriété accessible en lecture et en écriture dans la classe ancêtre. La classe descendante DOIT redéclarer toutes les propriétés et méthodes publiques de l'ancêtre sans rien changer à la déclaration, puis référencer l'objet ancêtre afin que votre classe soit étroitement reliée à cet ancêtre. VB vous empêchera de compiler votre programme tant que toutes ces déclarations ne seront pas présentes dans votre code.
Vous remarquerez que chaque déclaration a un nom qui est préfixé du nom de la classe ancêtre suivi d'un espace souligné. Ces déclarations sont l'épine dorsale de la classe héritée. Si vous voulez mettre du code spécifique à votre classe pour se substituer ou s'ajouter à celui de l'ancêtre, c'est là qu'il faut le mettre. Enfin, ces déclarations sont privées, par convention. A moins de vouloir vous prendre la tête plus tard, il n'y a aucun intérêt à les rendre publiques.
Code :
|
Enfin, comme vous héritez d'une classe, il faut écrire une interface publique correspondant à celle de l'ancêtre. Le compilateur ne vous obligera pas à écrire ces déclarations-ci, mais pour la sauvegarde de l'aspect objet de la chose, il vous faudra le faire. Comme la technique de l'héritage consiste à étendre une interface existante, il est donc obligatoire de publier cette même interface, sans quoi vous ne verrez rien d'un point de vue extérieur.
En C++, il aurait juste fallu écrire:
Code :
|
Voilà, avec tout ça, vous avez l'équivalent d'une seule ligne écrite dans un autre langage objet, mais pour des raisons qui nous échappent, nous ne pouvons pas nous contenter d'une ligne en VB (sauf si votre classe est vide, ce qui ne présenterait aucun intérêt).
Le polymorphisme
Mettons une classe ancêtre qui va décrire les caractéristiques techniques d'un avion en général, à moteur je le précise, histoire qu'on vienne pas me bourrer le mou avec les planeurs. Un avion se caractérise généralement par son type, le nombre de moteurs, ses dimensions, le nombre de places disponibles (il faut bien que le pilote s'assoit quelque part!), et son nom (type d'avion). Appelons cette classe AncetreAvion.
Il existe différents types d'avions: tourisme, de ligne, cargo, de chasse, bombardier, etc. Et imaginons que chacun de ces types d'avions soit une classe héritée de AncetreAvion. Ca va déjà faire un paquet de code, rien que parce que nous sommes en VB (et aussi parce que Microsoft fait chier )
Imaginons que nous soyons une compagnie de transport, et que notre parc de véhicules est plutôt hétéroclite puisque nous transportons personnes et marchandises, en plus de matériel ou personnel militaire. Et tout d'un coup, nous avons une énorme envie de compter rapidement le nombre de places disponibles pour l'ensemble. Mais comment faire ça *rapidement*? Faut-il le faire séparément pour chaque type d'avion puisqu'il s'agit chaque fois d'une classe différente?
La réponse est non! Comme nous l'avons dit précédemment, le nombre de places est une caractéristique de l'ancêtre, et comme tous les types d'avions dérivent de l'ancêtre, ils disposent d'au moins cette caractéristique. Le polymorphisme consiste à exploiter les caractéristiques communes de différentes classes héritant d'un même ancêtre. Pour cela, on fait passer n'importe quel type d'avion pour l'ancêtre.
Imaginons que tous nos avions soient dans une collection, peu importe leur type, collection qui retourne des éléments de type AncetreAvion. Chaque fois que nous allons accéder à un élément de cette collection, nous allons évidemment considérer qu'il s'agit du type AncetreAvion, et l'exploiter comme tel. A la fin d'une boucle parcourant tous les éléments de cette collection, nous connaîtrons le nombre total de places disponibles.
Code :
|
Il faut savoir que lorsque vous lisez la propriété Places de l'objet UnAvion, c'est la déclaration suivante qui intervient:
Code :
|
et non le code
Code :
|
Voilà donc révélée l'utilité cachée de cette déclaration tout à fait biscornue, j'en conviens.
Marsh Posté le 28-11-2003 à 10:58:54
drasche a écrit : Premier sujet: |
Je suppose que la chaine de connection change complètement suivant ce qu'on utilise...
Tu saurais où je peux trouver de la doc là-dessus?
Marsh Posté le 28-11-2003 à 11:07:13
il y a un excellent truc pour gérer cette chaîne de connexion, un "wizard caché" dans VB. Tu vas dans les composants et tu choisis le Microsoft ADO Data Control 6.0. Il apparaîtra alors dans ta toolbox . Tu le glisses sur une Form, et tu vas sur la propriété Custom. Dedans, tu auras tout ce qu'il faut pour générer ta ConnectionString. Elle ne change pas complètement d'un provider à un autre, mais il est vrai qu'ils ont chacun quelques particularités. Toutefois, tout est pris en charge par le wizard ou presque (Pour Access, il faut spécifier à la main le fichier de sécurité par exemple).
Marsh Posté le 28-11-2003 à 11:09:54
drasche a écrit : il y a un excellent truc pour gérer cette chaîne de connexion, un "wizard caché" dans VB. Tu vas dans les composants et tu choisis le Microsoft ADO Data Control 6.0. Il apparaîtra alors dans ta toolbox . Tu le glisses sur une Form, et tu vas sur la propriété Custom. Dedans, tu auras tout ce qu'il faut pour générer ta ConnectionString. Elle ne change pas complètement d'un provider à un autre, mais il est vrai qu'ils ont chacun quelques particularités. Toutefois, tout est pris en charge par le wizard ou presque (Pour Access, il faut spécifier à la main le fichier de sécurité par exemple). |
ok je regarde ça!:jap:
Marsh Posté le 28-11-2003 à 11:18:21
drasche a écrit : il y a un excellent truc pour gérer cette chaîne de connexion, un "wizard caché" dans VB. Tu vas dans les composants et tu choisis le Microsoft ADO Data Control 6.0. Il apparaîtra alors dans ta toolbox . Tu le glisses sur une Form, et tu vas sur la propriété Custom. Dedans, tu auras tout ce qu'il faut pour générer ta ConnectionString. Elle ne change pas complètement d'un provider à un autre, mais il est vrai qu'ils ont chacun quelques particularités. Toutefois, tout est pris en charge par le wizard ou presque (Pour Access, il faut spécifier à la main le fichier de sécurité par exemple). |
C'est censé être en option? Je le vois nulle part...:heink:
Marsh Posté le 12-03-2003 à 15:12:16
a) Ce topic parle de Visual Basic (version 6 pour l'essentiel) dans tous les sens, j'espère en couvrir avec le temps un maximum d'aspects, en espérant que vous y trouverez des infos utiles pour vous.
Tout d'abord, VB est-il gratuit?
Non, Visual Basic 6 n'est pas disponible gratuitement, même en version d'évaluation. La version étudiant est disponible (mais pour combien de temps encore?) pour environ 100?. Et la license indique que vous ne pouvez en faire un usage commercial. Voilà donc une réponse à une question régulièrement posée.
b) Les sujets suivants sont couverts:
1) connectivité aux bases de données (ADO et MySQL)
2) early binding vs. late binding
3) gestion des icônes dans la traybar
4) inclusion de ressources externes dans l'exécutable
5) les tableaux (arrays)
6) quelques considérations générales sur VB et son fonctionnement
7) support des skins Windows XP
8) les valeurs Null et Empty
9) Pourquoi dit-on que VB ne gère pas les objets? (ou comment "programmer objet" en VB?)
Premier sujet:
Visual Basic et MySQL
Le sujet est récurrent, alors je me suis décidé à faire un petit minimum pour montrer que ça n'est pas compliqué (et tout ça sans les API).
Voici une petite procédure d'exemple de connexion à une base de données (BD) MySQL. Cet exemple fait usage de l'API "ADO" (ActiveX Data Objects) de Microsoft. Autant dire qu'en Visual Basic, puisque vous êtes déjà à fond sous Windows, autant exploiter à fond ce qu'il vous offre. ADO en fait partie d'autant que Microsoft compte bien abandonner DAO, qui était la référence pour Access. La version utilisée d'ADO importe peu du moment qu'il s'agisse d'une version 2, qu'on trouve au moins sur tous les Windows 2000 et XP. Dans les autres cas, il est fort possible qu'il soit installé avec un autre produit Microsoft (Visual Studio, Office, ...).
Prérequis:
Le code qui suit se connecte à une DB MySQL locale, récupère quelques données et les affiche dans l'Immediate Window. L'avantage d'ADO est qu'il ne faut pas grand chose comme adaptations pour utiliser une autre base de données comme Access, SQL Server, ou Dieu sait ce que vous avez en tête. De la même manière, si vous venez justement d'une autre base de données et que vous comptez utiliser MySQL, très peu d'adaptations seront à faire. Je parle par expérience car j'ai migré il n'y a pas très longtemps une application faisant usage d'Access, vers MySQL et SQL Server.
Il est à noter que ce code, même s'il fait usage d'ODBC derrière, n'a pas besoin d'un DataSource défini dans le panneau de configuration ODBC. Tout ce qu'il faut est ici dans le code.
Ce code est bien entendu compilable, et a été testé par votre serviteur en local chez lui, en prenant une base de données existante comme exemple. J'ai juste changé son nom et créé un user particulier pour l'occasion.
N'hésitez pas à questionner et commenter. Si besoin est, je vous montrerai ensuite comment mettre à jour des données avec ADO, il existe plus d'une manière de le faire.
Option Explicit
Public Sub Main()
Dim oCon As Connection ' Connexion vers la BD
Dim oRst As Recordset ' Ensemble de données d'une table
Dim strConnect As String ' Chaîne de connexion vers la BD
Dim strSql As String
' Initialisation de la chaîne de connexion
strConnect = "DRIVER={MySQL ODBC 3.51 Driver};" & _
"SERVER=%server%;DATABASE=%database%;PORT=%port%;" & _
"UID=%userid%;PASSWORD=%password%;" & _
"OPTION=3;STMT=;"
' Insertion des paramètres dans la chaîne de connexion
strConnect = Replace(strConnect, "%server%", "localhost" ) ' Nom ou IP du serveur BD
strConnect = Replace(strConnect, "%port%", "3306" ) ' Port du serveur BD
strConnect = Replace(strConnect, "%database%", "dbtest" ) ' Nom de la BD
strConnect = Replace(strConnect, "%userid%", "usertest" ) ' Login pour la BD
strConnect = Replace(strConnect, "%password%", "mypassword" ) ' Mot de passe pour le login
' Initialisation de la connection
Set oCon = New Connection
Call oCon.Open(strConnect)
' Initialisation d'une requête
strSql = "SELECT ITLCATELLIB FROM TBLCATE"
Set oRst = New Recordset
' adOpenForwardOnly -> meilleur choix pour un parcours du recordset du début à la fin
' adCmdText -> on précise qu'il s'agit d'une requête
Call oRst.Open(strSql, oCon, adOpenForwardOnly, adLockReadOnly, adCmdText)
' Bouclage sur le recordset
Do While Not oRst.EOF
' Output dans l'immediate window
Debug.Print oRst!ITLCATELLIB
oRst.MoveNext
Loop
' Fermeture propre des connexions et destruction des objets
oRst.Close
Set oRst = Nothing
oCon.Close
Set oCon = Nothing
End Sub
Message édité par drasche le 11-05-2006 à 18:42:05
---------------
Whichever format the fan may want to listen is fine with us – vinyl, wax cylinders, shellac, 8-track, iPod, cloud storage, cranial implants – just as long as it’s loud and rockin' (Billy Gibbons, ZZ Top)