Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1961 connectés 

  FORUM HardWare.fr
  Programmation
  Divers

  [FAQ VB] La FAQ Visual Basic 6.0

 


 

 Mot :   Pseudo :  
 
 Page :   1  2  3  4  5  6
Page Précédente
Auteur Sujet :

[FAQ VB] La FAQ Visual Basic 6.0

n°330631
drasche
Posté le 12-03-2003 à 15:12:16  profilanswer
 

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:

  • installation du driver ODBC fourni par MySQL (version 3.51)
  • référencement du Microsoft ActiveX Data Objects 2.x (peu importe) comme ceci:


http://www.nightwing.easynet.be/pics/forums/faqs/vb6/refconmysql.png
 
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.
 

  • La première étape consiste à construire la "ConnectionString", qui définit les paramètres de la connexion à la BD: serveur, port, nom de la BD, et le login de l'utilisateur.
  • Un object de type Connection est construit.  Il s'appelle ici oCon.  La méthode Open, qui reçoit en paramètre cette ConnectionString, va ouvrir la connexion vers la BD.
  • Une fois connecté, on s'empresse de construire une petite requête SQL pour récupérer quelques données dans un objet de type Recordset.  On construit donc un objet de type Recordset (nommé oRst qu'on ouvre en lui passant la requête et l'objet de type Connection.  Les autres paramètres sont décrits dans le code.
  • Le recordset est ouvert, il suffit maintenant de parcourir celui-ci jusqu'à la fin tout en prélevant les informations dont on a besoin.
  • Une fois l'opération terminée, on ferme les connexions ouvertes, fin de la procédure.


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 cité 1 fois
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)
mood
Publicité
Posté le 12-03-2003 à 15:12:16  profilanswer
 

n°331080
skylight
Made in France.
Posté le 12-03-2003 à 19:41:09  profilanswer
 

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 :)

n°331083
skylight
Made in France.
Posté le 12-03-2003 à 19:42:21  profilanswer
 

Je voudrais également en savoir plus sur la fonction oCon.Open :  
 
que renvoie-t-elle en cas d'erreur ? (si elle renvoie quelque chose ..)

n°331087
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 12-03-2003 à 19:43:38  profilanswer
 

Drasche > je n'ai pas eu de GPF, c'est normal ? :heink:
 
 
[:dehors2]


---------------
J'ai un string dans l'array (Paris Hilton)
n°331088
drasche
Posté le 12-03-2003 à 19:43:43  profilanswer
 

ça génère une erreur vb mais avec un message venant d'ADO.  Tout dépend de la nature de l'erreur


---------------
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)
n°331095
skylight
Made in France.
Posté le 12-03-2003 à 19:45:26  profilanswer
 

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*
 


Message édité par skylight le 12-03-2003 à 19:52:16
n°331100
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 12-03-2003 à 19:46:58  profilanswer
 

Skylight a écrit :

Harkonnen > pour un modo, c'est une sale blague :D


on peut pas être bon tout le temps [:sinclaire]


---------------
J'ai un string dans l'array (Paris Hilton)
n°331107
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 12-03-2003 à 19:49:25  profilanswer
 

Skylight a écrit :

On peut néanmoins être plus bon que mauvais :D

un peu de sérieux svp, sinon je ferme le tomic ! :non:
 
et d'ailleurs,
 
[:dehors]


---------------
J'ai un string dans l'array (Paris Hilton)
n°331149
drasche
Posté le 12-03-2003 à 20:13:09  profilanswer
 

Skylight a écrit :

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*


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 [:spamafote]


---------------
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)
n°331159
skylight
Made in France.
Posté le 12-03-2003 à 20:16:25  profilanswer
 

Bon je vais relire mon MSDN ... pfiouu c dur de reprendre le VB :D

mood
Publicité
Posté le 12-03-2003 à 20:16:25  profilanswer
 

n°332544
skylight
Made in France.
Posté le 13-03-2003 à 20:55:11  profilanswer
 

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 ?

n°332563
drasche
Posté le 13-03-2003 à 21:10:58  profilanswer
 

manière classique:

Code :
  1. Public Sub Main
  2.    On Error Goto ErrHandler
  3.  
  4.    ... ton code ...
  5.  
  6.    Exit Sub
  7. ErrHandler:
  8.    MsgBox Err.Number & " " & Err.Description
  9. End Sub


Message édité par drasche le 11-05-2006 à 18:42:45

---------------
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)
n°332569
skylight
Made in France.
Posté le 13-03-2003 à 21:14:33  profilanswer
 

merci :)

n°341211
drasche
Posté le 24-03-2003 à 11:47:12  profilanswer
 

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 :
  1. Public Const lHM_NIM_ADD As Long = &H0      ' Add an icon
  2. Public Const lHM_NIM_MODIFY As Long = &H1   ' Modify an icon
  3. Public Const lHM_NIM_DELETE As Long = &H2   ' Delete an icon
  4.  
  5. Public Const lHM_NIF_MESSAGE As Long = &H1  ' To change uCallBackMessage member
  6. Public Const lHM_NIF_ICON As Long = &H2     ' To change the icon
  7. Public Const lHM_NIF_TIP As Long = &H4      ' To change the tooltip text
  8.  
  9. ' Windows standard constants
  10. Public Const WM_MOUSEMOVE As Long = &H200
  11. Public Const WM_LBUTTONDOWN As Long = &H201   ' Left click
  12. Public Const WM_LBUTTONDBLCLK As Long = &H203 ' Left double click
  13. Public Const WM_RBUTTONDOWN As Long = &H204   ' Right click
  14. Public Const WM_RBUTTONDBLCLK As Long = &H206 ' Right double click
  15.  
  16. ' Windows standard types
  17. Public Type NOTIFYICONDATA
  18.    cbSize As Long ' size of this structure
  19.    hwnd As Long ' handle of parent window
  20.    Uid As Long ' Used only with multiple icons associated
  21.                ' with the same application
  22.    uFlags As Long ' Flags
  23.    uCallBackMessage As Long ' Notifications handler
  24.    hIcon As Long ' Icon
  25.                  ' handle of the icon
  26.    szTip As String * 64 ' Tooltip text
  27. End Type
  28.  
  29. Public Declare Function Shell_NotifyIcon Lib "shell32" _
  30.               Alias "Shell_NotifyIconA" _
  31.               (ByVal dwMessage As Long, _
  32.               ByRef pnid As NOTIFYICONDATA) As Boolean


 
Déclarer la variable suivante dans une form:

Code :
  1. Private nid As NOTIFYICONDATA


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 :
  1. ' Taille de la structure
  2. nid.cbSize = Len(nid)
  3. ' handle de la form
  4. nid.hwnd = Me.hwnd
  5. nid.Uid = 0
  6. ' Indique qu'on souhaite placer une icône dans la traybar (lHM_NIF_ICON),
  7. installer un tooltip (lHM_NIF_TIP), et recevoir des messages systèmes (lHM_NIF_MESSAGE)
  8. nid.uFlags = lHM_NIF_ICON Or lHM_NIF_TIP Or lHM_NIF_MESSAGE
  9. ' Le message qui reviendra à la form est WM_MOUSEMOVE (elle recevra aussi les
  10. clics souris)
  11. nid.uCallBackMessage = WM_MOUSEMOVE
  12. ' Icône de la form
  13. nid.hIcon = Me.Icon
  14. ' Tooltip, finit toujours par vbNullChar
  15. nid.szTip = strTitle + vbNullChar


Comment ajouter l'icône à la traybar:

Code :
  1. Call Shell_NotifyIcon(lHM_NIM_ADD, nid)


Comment détruire l'icône de la traybar:

Code :
  1. Call Shell_NotifyIcon(lHM_NIM_DELETE, nid)


Message édité par drasche le 11-05-2006 à 18:43:15

---------------
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)
n°341298
MagicBuzz
Posté le 24-03-2003 à 12:40:11  profilanswer
 

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 :
  1. Dim cnx as Object ' Pointeur sur un objet générique, de taille non définie
  2. Dim rs as Object
  3. on error resume next ' Trappage des erreurs
  4. set cnx = createobject("ADODB.Connection" )
  5. set rs = createobject("ADODB.Recordset" )
  6. if err <> 0 then
  7.    msgbox("Vous ne pouvez vous connecter à une base de donnés, veuillez installer MDAC 2.x pour utliser cette fonction." )
  8.    set rs = nothing 'libération de la mémoire
  9.    set cnn = nothing
  10.    exit sub
  11. end if
  12. on error goto 0 ' On ne trappe plus les erreurs à partir de maintenant.
  13. set cnx.connectionstring = "..."
  14. cnx.open
  15. set rs.activeconnection = cnx
  16. rs.open "select * from tabuser"
  17. do while not rs.eof
  18.   ... ' Traîtements
  19.   rs.movenext
  20. loop
  21. rs.close
  22. set rs = nothing
  23. cnx.close
  24. set cnx = nothing


 
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.


Message édité par MagicBuzz le 24-03-2003 à 12:40:47
n°341390
drasche
Posté le 24-03-2003 à 13:27:31  profilanswer
 

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 :D) 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éé.


---------------
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)
n°341478
MagicBuzz
Posté le 24-03-2003 à 15:04:50  profilanswer
 

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 ?

n°341486
drasche
Posté le 24-03-2003 à 15:10:49  profilanswer
 

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 :D
 
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 :jap:


Message édité par drasche le 24-03-2003 à 15:14: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)
n°342246
C17
-$$ W A N T E D $$-
Posté le 25-03-2003 à 09:48:44  profilanswer
 

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?


---------------
C17
n°342296
drasche
Posté le 25-03-2003 à 10:25:31  profilanswer
 

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 :/


---------------
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)
n°355403
drasche
Posté le 08-04-2003 à 09:11:29  profilanswer
 

J'y pense seulement maintenant: comment introduire des ressources custom dans un programme VB6.
 
http://forum.hardware.fr/forum2.ph [...] 664&cat=10


Message édité par drasche le 07-10-2003 à 13:49:48

---------------
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)
n°361353
toutoun88
Posté le 15-04-2003 à 10:49:02  profilanswer
 

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?

n°367894
C17
-$$ W A N T E D $$-
Posté le 21-04-2003 à 20:30:28  profilanswer
 

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.

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 :/


Pour le point 1, ça fonctionne très bien avec un timer  :jap:  
 
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...


Message édité par C17 le 21-04-2003 à 20:35:56

---------------
C17
n°402774
drasche
Posté le 21-05-2003 à 14:44:45  profilanswer
 

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 :
  1. Dim ary(5)


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 :
  1. Dim ary(2 to 5)


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 :
  1. Public Sub TestTableaux1a()
  2.    ' Un tableau avec bornes prédéfines (cette méthode-ci est à proscrire)
  3.    ' Les seules opérations possibles sont de lire et écrire dans le tableau,
  4.    '   sinon erreur de compilation.
  5.    Dim ary(2 To 5) As Integer
  6.  
  7.    Debug.Print "TestTableaux1a()"
  8.  
  9.    ' seuls ces éléments sont assignables!
  10.    ary(2) = 1
  11.    ary(3) = 5
  12.    ary(4) = 16
  13.    ary(5) = 10
  14.  
  15.    Call Array2Immediate(ary)
  16. End Sub
  17.  
  18. Public Sub TestTableaux1b()
  19.    ' un tableau dont on fixe la borne supérieure.
  20.    ' la borne inférieure est implicitement zéro.
  21.    ' Les seules opérations possibles sont de lire et écrire dans le tableau,
  22.    '   sinon erreur de compilation.
  23.    Dim ary(2) As Integer
  24.  
  25.    Debug.Print "TestTableaux1b()"
  26.  
  27.    ary(0) = 100
  28.    ary(1) = 30
  29.    ary(2) = 1
  30.  
  31.    Call Array2Immediate(ary)
  32. End Sub


 
Cas 2: les tableaux dynamiques
 
Ils se déclarent comme ceci:

Code :
  1. Dim ary()


 
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 :
  1. Redim ary(5)


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 :
  1. Redim Preserve ary(6)


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 :
  1. Public Sub TestTableaux2()
  2.    ' Tableau déclaré mais non dimensionné.  Il doit être dimensionné avant
  3.    '   de lire ou écrire dedans
  4.    ' Le tableau peut être redimensionné selon les besoin, notamment en
  5.    '   préservant les données existantes
  6.    Dim ary() As Integer
  7.  
  8.    Debug.Print "TestTableaux2() résultat 1"
  9.  
  10.    ReDim ary(1) ' réserve 2 éléments de type integer
  11.  
  12.    ary(0) = 1
  13.    ary(1) = 5
  14.  
  15.    Call Array2Immediate(ary)
  16.  
  17.    Debug.Print "TestTableaux2() résultat 2"
  18.  
  19.    ReDim ary(2) ' réserve 3 éléments de type integer
  20.                 ' les éléments existants sont écrasés
  21.  
  22.    ary(2) = 7
  23.  
  24.    Call Array2Immediate(ary)
  25.  
  26.    Debug.Print "TestTableaux2() résultat 3"
  27.  
  28.    ary(0) = 1
  29.    ary(1) = 5
  30.    ReDim Preserve ary(3) ' réserve un élément supplémentaire
  31.                          ' le contenu existant n'est pas écrasé
  32.    ary(3) = 10
  33.  
  34.    Call Array2Immediate(ary)
  35. End Sub


 
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 :
  1. Public Sub TestTableaux3()
  2.    ' un variant peut cacher tout type de variable, y compris un tableau
  3.    Dim ary As Variant
  4.    Dim strArray As String
  5.  
  6.    Debug.Print "TestTableaux3() résultat 1"
  7.  
  8.    strArray = "10;651;135;31;9"
  9.    ary = Split(strArray, ";" )
  10.  
  11.    ' Split prend le ";" comme séparateur de liste, et prend les
  12.    '   éléments séparés par le ";" pour construire un tableau.
  13.    ' Cette opération n'est possible que si la variable qui reçoit
  14.    '   le tableau est un pur variant.
  15.    'ary = Split(strArray, ";" )
  16.  
  17.    Call Array2Immediate(ary)
  18.  
  19.    Debug.Print "TestTableaux3() résultat 2"
  20. End Sub


 
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 :
  1. Dim ary(5, 2, 4)


Alors:

Code :
  1. Debug.Print UBound(ary, 3)


renverra 4.  Oui, les dimensions se comptent à partir de 1 jusqu'à n dimensions.
 

Code :
  1. Public Sub TestTableaux4()
  2.    Dim ary() As Variant
  3.  
  4.    Debug.Print "TestTableaux4()"
  5.  
  6.    ' Attention!  Sur un Redim Preserve, seule la dernière dimension
  7.    '   peut être changée!
  8.    ReDim ary(5, 0) ' OK: réservation d'une ligne de 5 colonnes
  9.    ReDim Preserve ary(5, 1) ' OK: réservation de ligne(s) supplémentaire(s)
  10.                             ' sur 5 colonnes
  11.  
  12.    ReDim ary(3, 1) ' OK: dimensionnement sans préservation de l'existant
  13.    'ReDim Preserve ary(2, 1) ' Pas OK: redimensionnement en tentant de changer
  14.                             ' la première dimension
  15.  
  16.    ' Référence vers un élément:
  17.    Debug.Print "test ary(2, 1)", ary(2, 1)
  18. End Sub


 
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 :pt1cable:
Rassurez vous, je vais rester avec des tableaux à une seule dimension pour rester clair ;)
 

Code :
  1. Public Sub TestTableaux5()
  2.    Dim ary As Variant
  3.  
  4.    Debug.Print "TestTableaux5()"
  5.  
  6.    ReDim ary(1) ' Redéclaration du tableau à deux éléments
  7.  
  8.    ' assignation d'un tableau à un tableau
  9.    ary(0) = Split("10;651;135;31;9", ";" )
  10.    ary(1) = Split("64;61;479;68;4;79;68;684", ";" )
  11.  
  12.    ' Référence vers un élément: comme nous avons des tableaux
  13.    '   dans les tableaux, il faut les traiter comme tels:
  14.    Debug.Print "test ary(0, 4)", ary(0)(4)
  15.    Debug.Print "test ary(1, 3)", ary(1)(3)
  16.  
  17.    Call Array2Immediate(ary(0))
  18.    Call Array2Immediate(ary(1))
  19. End Sub


 
 
Et pour terminer (et pour l'exemple), voici la fonction Array2Immediate:
 

Code :
  1. Public Sub Array2Immediate(ByRef ary As Variant)
  2.    Dim i As Integer
  3.  
  4.    ' Parcours séquentiel d'un array à une dimension
  5.    '   depuis le premier élément jusqu'au dernier.
  6.    ' * LBound renvoie l'indice du premier élément;
  7.    ' * UBound renvoie l'indice du dernier élément.
  8.  
  9.    ' Une fonction IsArray() permet de savoir s'il
  10.    '   s'agit bien d'un tableau (même non-dimensionné)
  11.    '   lorsqu'on a une variable de type Variant
  12.    If IsArray(ary) Then
  13.        On Error GoTo ErrHandler
  14.        For i = LBound(ary) To UBound(ary)
  15.            Debug.Print "Element " & i, ary(i)
  16.        Next i
  17.    Else
  18.        Debug.Print "ary n'est pas un array"
  19.    End If
  20.    Debug.Print vbCrLf
  21.    Exit Sub
  22. ErrHandler:
  23.    If Err.Number = 9 Then ' Subscript out of range
  24.        Debug.Print "Erreur rencontrée, ary est un tableau non dimensionné"
  25.    Else
  26.        Debug.Print "Erreur non-gérée"
  27.    End If
  28. End Sub


Message édité par drasche le 11-05-2006 à 18:43:52
n°448761
drasche
Posté le 04-07-2003 à 14:27:38  profilanswer
 

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 :
  1. ? 68742 / (3600 * 24)


 
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 :
  1. Dim i As Integer
  2. Dim b As Byte
  3. Dim l As Long
  4.  
  5. b = 24
  6. i = 3600
  7. l = i * b


 
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]


Message édité par drasche le 11-05-2006 à 18:48:01

---------------
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)
n°516604
C17
-$$ W A N T E D $$-
Posté le 17-09-2003 à 15:56:58  profilanswer
 

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 :
  1. Dim cn As New ADODB.Connection
  2. Dim rsClient As New ADODB.Recordset
  3. Dim rsTel As New ADODB.Recordset
  4. Private Sub Form_Load()
  5. cn.CursorLocation = adUseClient
  6. cn.Open "Provider=MSDataShape;Data Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Cours_VB\Cours Visual Basic\Projet 2\BFormation.mdb;Persist Security Info=False"
  7. rsClient.Open " SHAPE {SELECT * FROM `TableStagiaire`}  AS Command1 APPEND ({SELECT * FROM `TableTel`}  AS Command3 RELATE 'NumAuto' TO 'NumStag') AS Command2", cn, adOpenStatic, adLockOptimistic
  8. Set rsTel = rsClient.Fields("command2" ).Value
  9. Set DataGrid1.DataSource = rsClient
  10. Set DataGrid2.DataSource = rsTel
  11. End Sub


 
Voili voilou!


Message édité par C17 le 17-09-2003 à 18:42:32

---------------
C17
n°516706
drasche
Posté le 17-09-2003 à 18:16:40  profilanswer
 

Merci :jap:
 
faudra que j'essaie ça une fois rentré au boulot :D


---------------
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)
n°516714
C17
-$$ W A N T E D $$-
Posté le 17-09-2003 à 18:40:48  profilanswer
 

drasche a écrit :

Merci :jap:
 
faudra que j'essaie ça une fois rentré au boulot :D


 
ça fonctionne super et en plus on est pas limité à une arborescence à un seul niveau comme avec le DataEnvironment... :sol:

n°528180
Mr yvele
yvele n'est plus.
Posté le 01-10-2003 à 21:00:23  profilanswer
 

Merci drasche! franchement excellent
 :jap:  :jap:  :jap:


Message édité par Mr yvele le 01-10-2003 à 22:56:27
n°529742
C17
-$$ W A N T E D $$-
Posté le 02-10-2003 à 21:18:55  profilanswer
 

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!

n°529749
drasche
Posté le 02-10-2003 à 21:28:10  profilanswer
 

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.

n°533280
drasche
Posté le 07-10-2003 à 14:42:55  profilanswer
 

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 :
  1. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  2. <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  3.     <assemblyIdentity version="1.0.0.0" processorArchitecture="X86"
  4.                                         name="Microsoft.Visual.Basic.6.0" type="win32" />
  5.     <description>CodoBrowser</description>
  6.     <dependency>
  7.         <dependentAssembly>
  8.         <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls"
  9.                                             version="6.0.0.0" processorArchitecture="X86"
  10.                                          publicKeyToken="6595b64144ccf1df" language="*" />
  11.         </dependentAssembly>
  12.  </dependency>
  13. </assembly>


 
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 :
  1. #define CREATEPROCESS_MANIFEST_RESOURCE_ID 1
  2. #define RT_MANIFEST 24
  3. CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "votreapplication.manifest"


 
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 :
  1. ' Windows XP styles
  2. Private Type tagInitCommonControlsEx
  3.   lngSize As Long
  4.   lngICC As Long
  5. End Type
  6.  
  7. Private Const ICC_USEREX_CLASSES = &H200
  8.  
  9. Private Declare Function InitCommonControlsEx _
  10.                Lib "comctl32.dll" _
  11.                (iccex As tagInitCommonControlsEx) As Boolean
  12.  
  13. ' Change application GUI style -> Windows XP compatibility
  14. Public Function InitCommonControlsVB() As Boolean
  15. On Error Resume Next
  16.    Dim iccex As tagInitCommonControlsEx
  17.    ' Ensure CC available:
  18.    iccex.lngSize = LenB(iccex)
  19.    iccex.lngICC = ICC_USEREX_CLASSES
  20.    End With
  21.    call InitCommonControlsEx(iccex)
  22.    InitCommonControlsVB = (Err.Number = 0)
  23. On Error GoTo 0
  24. End Function


 
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:
 
http://www.nightwing.easynet.be/pics/forums/faqs/vb6/noskin.png
 
    Et la fenêtre skinnée sans aucun changement (thème MacOS X)
 
http://www.nightwing.easynet.be/pics/forums/faqs/vb6/skinbugged.png
 
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:
 
http://www.nightwing.easynet.be/pics/forums/faqs/vb6/skingood.png
 
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.


Message édité par drasche le 11-05-2006 à 18:50:05
n°551448
drasche
Posté le 27-10-2003 à 13:26:16  profilanswer
 

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.


Message édité par drasche le 27-10-2003 à 13:26:35

---------------
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)
n°551803
Mr yvele
yvele n'est plus.
Posté le 27-10-2003 à 18:59:30  profilanswer
 

merci drasche :jap:
 
[:prosterne]


Message édité par Mr yvele le 27-10-2003 à 18:59:54

---------------
yvele n'est plus.
n°553040
drasche
Posté le 28-10-2003 à 22:14:13  profilanswer
 

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 :
  1. Option Explicit
  2.  
  3. Private ppvValue As Long
  4.  
  5. Private Sub Class_Initialize()
  6.    ppvValue = 1
  7. End Sub
  8.  
  9. Public Property Get Value() As Long
  10.    Value = ppvValue
  11. End Property
  12.  
  13. Public Property Let Value(X As Long)
  14.    ppvValue = X
  15. End Property


 
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 :
  1. Set MonObjet = New MaClasse


 
et se détruit comme suit:
 

Code :
  1. Set MonObjet = Nothing


 
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 :
  1. Set MaReference = MonObjet


 
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 :
  1. ' J'instancie une classe en mémoire et MonObjet en reçoit la référence: mon objet est né.
  2. Set MonObjet = New MaClasse
  3. ' Je copie la référence de mon objet dans une autre variable
  4. Set MaReference = MonObjet
  5. ' J'efface la référence de mon objet de la première variable
  6. ' Mais il n'est pas mort car MaReference dispose également d'une référence vers mon objet
  7. Set MonObjet = Nothing
  8. ' Cette fois, c'est bon! Il n'y a plus de référence vers l'instance de ma classe, mon objet est donc bien mort
  9. Set MaReference = Nothing


 
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 :
  1. Option Explicit


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 [:cupra]
 

Code :
  1. Implements ClasseAncetre


Ceci est la ligne unique qu'on trouverait dans un autre langage et qui dit: je veux hériter de ClassAncetre.
 

Code :
  1. Private ppvoAncetre As ClasseAncetre
  2.  
  3. Private Sub Class_Initialize()
  4.    Set ppvoAncetre = New ClasseAncetre
  5. End Sub
  6.  
  7. Private Sub Class_Terminate()
  8.    Set ppvoAncetre = Nothing
  9. End Sub


 
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 :
  1. Private Property Let ClasseAncetre_Value(X As Long)
  2.    ppvoAncetre.Value = X
  3. End Property
  4.  
  5. Private Property Get ClasseAncetre_Value() As Long
  6.    ClasseAncetre_Value = ppvoAncetre.Value
  7. End Property


 
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 :
  1. Public Property Get Value() As Long
  2.    Value = ClasseAncetre_Value
  3. End Property
  4.  
  5. Public Property Let Value(X As Long)
  6.    ClasseAncetre_Value = X
  7. End Property


 
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 :
  1. class ClassDescendant: public ClassAncetre {
  2. };


 
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 :fou:)
 
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 :
  1. Public Function GetPlaces() As Long
  2.  Dim UnAvion As AncetreAvion
  3.  Dim NombrePlaces As Long
  4.  
  5.  NombrePlaces = 0
  6.  For Each UnAvion In  CollectionAvions
  7.     NombrePlaces = NombrePlaces + UnAvion.Places
  8.  Next UnAvion
  9.  
  10.  GetPlaces = NombrePlaces


 
Il faut savoir que lorsque vous lisez la propriété Places de l'objet UnAvion, c'est la déclaration suivante qui intervient:
 

Code :
  1. Private Property Get AncetreAvion_Places() As Long
  2.    AncetreAvion_Places = ppvoAncetre.Places
  3. End Property


 
et non le code  

Code :
  1. Public Property Get Places() As Long
  2.    Places = AncetreAvion_Places
  3. End Property


 
Voilà donc révélée l'utilité cachée de cette déclaration tout à fait biscornue, j'en conviens.


Message édité par drasche le 11-05-2006 à 18:37:35

---------------
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)
n°578011
skeye
Posté le 28-11-2003 à 08:54:41  profilanswer
 

[:drapo]

n°578102
skeye
Posté le 28-11-2003 à 10:58:54  profilanswer
 

drasche a écrit :

Premier sujet:
 
Visual Basic et MySQL
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 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?

n°578112
drasche
Posté le 28-11-2003 à 11:07:13  profilanswer
 

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).


---------------
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)
n°578115
skeye
Posté le 28-11-2003 à 11:09:54  profilanswer
 

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:


Message édité par skeye le 28-11-2003 à 11:10:07
n°578123
skeye
Posté le 28-11-2003 à 11:18:21  profilanswer
 

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:

mood
Publicité
Posté le   profilanswer
 

 Page :   1  2  3  4  5  6
Page Précédente

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  Divers

  [FAQ VB] La FAQ Visual Basic 6.0

 

Sujets relatifs
[BASIC] comment "dérouler" les GOTO ???Mysql et Visual Basic 6.0 - Connecter les 2 ?
[Outil de programmation] Visual Studio .net 2002 pro frVisual c++ 6.0 questions ?
FAQ programmationvisual C++ cours/tutoriels
[BASIC] Exporter une donnée de la base de registre[VISUAL STUDIO 6]Warning bizarre - conseil
[HELP] turbo basic :p 
Plus de sujets relatifs à : [FAQ VB] La FAQ Visual Basic 6.0


Copyright © 1997-2018 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR