Accueil
Club Emploi Blogs   TV   Dév. Web PHP XML Python Autres 2D-3D-Jeux Sécurité Windows Linux PC Mac
Accueil Conception Java DotNET Visual Basic  C  C++ Delphi Eclipse MS-Office SQL & SGBD Oracle  4D  Business Intelligence

Cours VB.NET

Date de mise à jour : 05/12/2010


XV-A. Programmation orientée objet, Propriétés des Classes (Rappel)
XV-A-1. Interface et Implémentation
XV-A-2. Encapsulation
XV-A-3. Héritage
XV-A-4. Polymorphisme
XV-A-5. Constructeur, destructeur
XV-A-6. Accesseur, mutateur
XV-A-7. Déclaration, instanciation
XV-A-8. Propriétés, Méthodes
XV-A-9. Les Classes : elles sont 'By Ref'
XV-A-9-a. Création de variable objet
XV-A-9-b. Affectation
XV-A-9-c. Comparaison
XV-A-10. Nommage
XV-B. Créer une Classe
XV-B-1. Création de Classe
XV-B-1-a. Revenons une nouvelle fois sur la notion de Classe et d'Objet
XV-B-1-b. Créer une Classe
XV-B-1-c. Ajouter des variables dans une classe
XV-B-1-d. Ajouter des propriétés grâce à 'Property'
XV-B-1-e. Méthode
XV-B-1-f. Récapitulatif Property, méthodes
XV-B-1-g. Constructeur
XV-B-1-h. Destructeur
XV-B-1-i. Surcharge
XV-B-1-j. Évènement
XV-B-1-k. Exception
XV-B-1-l. Les Classes partielles
XV-B-1-m. Méthode partielles
XV-B-2. Classe suite et astuces
XV-B-2-a. Me, My, MyClass, MyBase
XV-B-2-b. Propriété par défaut
XV-B-2-c. Méthode de Classe avec Shared
XV-B-2-d. Création d'un compteur d'instances
XV-B-2-e. Création d'un identifiant unique d'instance
XV-B-2-f. Singleton
XV-B-2-g. Surcharge d'opérateur
XV-B-2-h. Surcharge de ToString
XV-C. Créer un composant (Bibliothèque de Classe et de Contrôles)
XV-C-1. Créer une Bibliothèque de classes
XV-C-1-a. Namespace
XV-C-1-b. Utilisation du composant
XV-C-2. Créer un 'contrôle utilisateur' à partir d'un contrôle existant en le modifiant
XV-C-3. Créer un 'contrôle utilisateur' contenant un ou plusieurs contrôles pilotés


XV-A. Programmation orientée objet, Propriétés des Classes (Rappel)

VB.NET permet maintenant de faire de la POO (Programmation Orientée Objet)à part entière:

Il y a:

Les Classes du FrameWork.

On peut aussi CREER soi même (dans des modules de Classe) de nouvelles Classes qui suivront elles aussi les règles de la POO. Ces classes serviront à instancier des objets.

info Pour ce chapitre, nous sommes du coté de l'application utilisatrice des objets (et non dans les objets).
L'objet est une boite (jaune ici!!), je l'utilise , mais je ne sais pas ce qui se passe à l'intérieur.

XV-A-1. Interface et Implémentation

Nous savons déjà:

On utilise une Classe (le moule) pour instancier (créer) un objet.

Une classe est une combinaison de code et de données.
  • Le code et la définition des données constituent l'implémentation (c'est à l'intérieur de la boite).
  • L'interface de l'objet est l'ensemble de ses membres visibles et utilisables (les membres sont les propriétés, les méthodes, les évènements).
Exemple:

Prenons un objet d'une classe ListBox:
  • L'interface ListBox.Visible ListBox.AddItem...c'est Je la vois , je peux l'utiliser.
  • L'implémentation, je ne la vois pas, c'est le code qui gère la ListBox, la définition des éléments; c'est une 'boite noire', je ne sais pas ce qui s'y passe, je n'y est pas accès, et c'est tant mieux!!!

XV-A-2. Encapsulation

Le fait de ne pas voir l'implémentation (le code), c'est l'encapsulation.

Le code, les définitions de données sont privés à l'objet et non accessibles, ils sont enfermés, encapsulés dans une boite noire.

info L'encapsulation permet donc d'exposer aux applications clientes uniquement l'interface.
Les applications clientes n'ont pas à se soucier du fonctionnement interne.

Cela a une conséquence, si je modifie le code mais pas l'interface, l'application cliente n'a pas à être modifiée.


XV-A-3. Héritage

On a vu qu'un objet issu d'une Classe dérivée hérite des membres de la classe de base (la classe parent), cela crée une relation mère/fille (parent/enfant); la classe fille pouvant réutiliser les membres de la classe mère.

A noter qu'une classe ne peut hériter que d'une classe en VB.NET.

La Classe fille peut utiliser les membres de la classe mère, mais aussi ajouter ses propres membres ou redéfinir certains membres de la classe mère.

Exemple:

On a vu que quand on dessine une Form1, cela crée une Classe 'Form1' qui hérite des Windows.Forms (Inherits System.Windows.Forms.Form)

Autre exemple:

ListBox hérite de Control


XV-A-4. Polymorphisme

Le nom de polymorphisme signifie "qui peut prendre plusieurs formes".

Tous les sites français donnent les mêmes définitions et entretiennent une certaine confusion. Il indiquent 3 types de polymorphisme et la différence entre polymorphisme 'paramétrique' de surcharge et ad ohc n'est pas évidente. Je vais donc expliquer les choses à ma manière!!

Il y a 4 sortes de polymorphisme:

  • Le polymorphisme ad hoc.

    Le polymorphisme ad hoc permet d'avoir des fonctions de même nom, avec des fonctionnalités similaires, dans des classes sans aucun rapport entre elles . Par exemple, la classe Integer, la classe Long et la classe Date peuvent avoir chacune une fonction ToString. Cela permettra de ne pas avoir à se soucier du type de l'objet que l'on a si on souhaite le transformer en String.

  • Le polymorphisme de ou en anglais .

    Une méthode gère des paramètres de type et de nom différents

    Ce polymorphisme représente la possibilité de définir plusieurs méthodes de même nom mais possédant des paramètres différents (en nombre et/ou en type).

    pour ouvrir une fenêtre MessageBox, la méthode Show a 12 signatures, en voici 2:

    Ici on donne 4 paramètres.
    
    Reponse= MessageBox.show(TexteAAfficher,Titre, TypeBouton etIcone, BoutonParDéfaut)
    
    Ici 1 seul paramètre.
    
    Reponse= MessageBox.show(TexteAAfficher)
    
    On appelle signature chaque combinaison d'arguments d'une fonction (combinaison en nombre et en type). Une fonction a donc autant de signatures que de manière d'appeler cette fonction C'est donc la signature d'une méthode qui détermine quel code sera appelé.

  • Le polymorphisme d'héritage (redéfinition, spécialisation ou en anglais overriding)
    Quand une classe hérite d'une autre classe, elle hérite des méthodes. On peut redéfinir substituer une méthode de la classe parent par une méthode de même nom dans la classe enfant.

  • Le polymorphisme générique ( en anglais template)
    C'est la forme la plus naturelle du polymorphisme: elle permet d'appeler la méthode d'un objet sans devoir connaître son type. En VB 2005 cela correspond aux générics.


XV-A-5. Constructeur, destructeur

Un constructeur est une fonction effectuée lors de l'instanciation d'un objet de la Classe; il sert généralement à 'initialiser' l'objet. Il est appelé quand on fait New.

Souvent il y a plusieurs signatures. Il y a habituellement un constructeur par défaut qui n'a pas de paramètres.

Exemple: pour créer un objet graphique Point, j'utilise un constructeur permettant de définir les coordonnées du point:

Dim P As New Point(45, 78)
La destruction d'un objet est effectué lorsqu'on lui affecte la valeur Nothing ou lorsqu'on quitte la portée où il a été défini.

P= Nothing

XV-A-6. Accesseur, mutateur

Un accesseur (accessor en anglais) est un membre renvoyant la valeur d'une propriété d'un objet.

MyObjet.GetName est un accesseur car elle renvoie la valeur de la propriété Name.

Un mutateur (mutator en anglais) ou encore modifieur (modifier en anglais) est un membre qui modifie la valeur d'une propriété d'un objet.

MyObjet.SetName est un mutateur car elle modifie la valeur de la propriété Name.


XV-A-7. Déclaration, instanciation

On peut déclarer et instancier en même temps:

Dim P As New MaClasse
On peut séparer les 2 actions:

Dim P As Maclasse    'déclaration

P As New Maclasse    'instanciation
La déclaration et l'instanciation peuvent être effectuées dans les endroits différents:

Module Mon module

    Public P As MaClasse

 

Sub MaRoutine

    P As New MaClasse

End Sub

End Module 
Ici P est déclaré comme Public, il est instancié dans une Sub.



XV-A-8. Propriétés, Méthodes

Un Objet peut avoir une ou des propriétés:

Dim B As New Button

B.Name ="toto"
Un Objet peut avoir une ou des Méthodes:

Dim B As New Button
B.Click est une méthode.


XV-A-9. Les Classes : elles sont 'By Ref'

On rappelle que les classes sont des Objets 'By Ref' (Par référence)

warning Il faut comprendre qu'une variable Objet contient la référence, le pointeur de l'objet, mais pas l'objet lui même.
Cela entraîne:


XV-A-9-a. Création de variable objet


Soit une classe Class1.


Dim I As Class1
On crée un pointeur vide, entraîne: I contient Nothing: il ne pointe sur aucun objet.


	I = New Class1
Maintenant I contient la référence, le pointeur vers un objet de type Class1

le constructeur New a bien crée une instance de Class1

Habituellement on utilise en une fois:

Dim I As New Class1  

On peut voir si la variable contient Nothing : If IsNothing( I ) then.. ou If I Is Nothing..


XV-A-9-b. Affectation

Si on affecte une variable par référence à une autre, elle pointe toutes les 2 sur le même endroit mémoire: si j'en modifie une, cela modifie l'autre.

'Créons une Classe contenant un entier.

Class Class1
   Public Value As Integer = 0
End Class

Dim C1 As New Class1()
Dim C2 As Class1 =C1    'on crée C2, on affecte C1 à C2
C2.Value = 123          'on modifie C2
 

=> C1.Value=123  C2.Value=123    
Modifier C2 a modifié C1 car elles pointent sur le même endroit mémoire.

On le redit autrement: quand on crée C1 et C2, il n'y a pas 2 objets C1 et C2 mais 2 pointeurs vers le même objet.


Si on veut faire une copie 'indépendante', il faut utiliser Clone.

Class Class1
   Public Value As Integer = 0
End Class

Dim C1 As New Class1()
C1.Value= 555
Dim C2 As Class1 =C1.Clone    'on crée C2, on clone 
C2.Value = 123          'on modifie C2
 
'C1.Value=555  C2.Value=123    


XV-A-9-c. Comparaison

Deux objets peuvent être comparés par "Is".

Dim O As Object

Dim Q As Object  

If O Is Q then..
Equals peut être utilisé pour la comparaison:

Obj1.Equals(Obj2))  'Retourne True si Obj1 et Obj2 ont le même pointeur.

XV-A-10. Nommage

Pour les noms de Classe, utiliser le case Pascal: Chaque mot qui compose le nom a sa première lettre en majuscule.

Exemple Class MaClasse

Idem pour les évènement, espace de nom, méthodes:

Exemple: System.Drawing, ValueChange..

Dans les objets, il ne faut pas inclure des noms de classe dans les noms de propriétés Patient.PatientNom est inutile, utiliser plutôt Patient.Nom.



XV-B. Créer une Classe


XV-B-1. Création de Classe

On a vu qu'il existait des classes prédéfinies (celle du Framework par exemple) mais on peut soi même

CREER SES PROPRES CLASSES:

Maintenant on est DANS la boite.

XV-B-1-a. Revenons une nouvelle fois sur la notion de Classe et d'Objet

On va créer une classe 'Médicament'( c'est l'objet de ce chapitre).

Un 'Médicament' possède les variables:

Nom
Laboratoire
Nombre de médicament.
.. 

Il faut donc pouvoir 'regrouper' ces variables pour un médicament précis. Pour regrouper ces variables, on utilise une structure particulière: la Classe.

Une Classe 'Medicament' aura:

Medicament.Nom
Medicament.Laboratoire
Medicament.NbdeMedicament

Avec cette Classe (la structure, le moule), on peut créer (instancier) un Objet MonMedicament.

Dim MonMedicament As New Medicament
Il comporte les propriétés (données):

MonMedicament.Nom
MonMedicament.Laboratoire
MonMedicament.NbdeMedicament

Il comporte des méthodes (comportement):

MonMedicament.GetNom est une méthode

L'utilisateur de l'objet ne voit que le nom de la méthode (l'interface), il ne voit pas le code de la procédure (l'implémentation). Il y a bien encapsulation.

Une fois cette classe créée, du coté utilisateur, comment l'utiliser?

Pour instancier un objet Medicament:

Dim MonMedicament As New Medicament()

Donner une valeur à une propriété:

MonMedicament.Nom= "Aspirine": MonMedicament.Laboratoire="RP"
Récupérer la valeur d'une propriété:

LeNom=MonMedicament.Nom  : Nb= MonMedicament.NombreMedicament
warning Pour la suite de ce chapitre, nous sommes DANS la Classe de l'objet ( et non dans l'application utilisatrice).

XV-B-1-b. Créer une Classe

Menu Projet puis Ajouter une Classe.

Entrée 'Medicament' dans la zone nom puis OK

Une nouvelle fenêtre de module est ajoutée à notre projet, contenant le code suivant:

Public Class Medicament
...
End Class
Le mot avant Class indique la portée de la classe:

  • Public (Classe instanciable dans et hors du projet, utilisable par un autre programme)
  • Private (Classe instanciable que dans elle même!!)
  • Friend (Classe instanciable dans le projet )
  • Protected (Classe instanciable uniquement dans les classes dérivées)

On peut ajouter:

MustInherit: Cela donne une classe non instanciable, on ne peut pas créer d'objet avec!! Alors à quoi cela sert!! A fournir une base pour des classes qui en hériteront. on appelle ces classes des classes abstraites.

NotInheritable: Cette classe ne peut-être héritée.


En vb 2010, si dans le code, on utilise une classe qui n'existe pas, vb souligne le nom de la classe et vous propose (en cliquant sur le bouton dessous) de créer une classe vide:



XV-B-1-c. Ajouter des variables dans une classe

On parle de variable ou 'Attribut' permettant d'associer des données à une Classe.

La variable peut être 'Privée' et non visible à l'extérieur:

Private _mNom As String 
Il est conseillé de mettre un '_' au début du nom d'une variable privée puis une majuscule au début de chaque mot sauf le premier.

Elle peut être 'Public' , visible à l'extérieur et donc non encapsulée.

Public Laboratoire As String
Il est conseillé de mettre une majuscule au début de chaque mot formant le nom de la variable public.

A l'extérieur , si on instance M comme un médicament (Dim M As New Médicament) , M.Laboratoire est valide.

On peut définir un champ 'Public' en lecture seule qui a une valeur constante:

Public ReadOnly NombreMedicament=2000
Vous pouvez ajouter à votre variable : Shared. Cela signifie que la variable déclarée comme Shared est partagée par toutes les instances de la classe : C'est une variable de classe et non une variable d'instance.
Une variable Shared est même utilisable sur le nom de la classe , sans instancier.


Exemple:

Public Class Medicament
    Public Laboratoire As String    'variable d'instance
    Public Shared Societe as String 'variable de classe Shared
End Class
 
Dim M1 As New Medicament
Dim M2 As New Medicament
 
M1.Laboratoire= "MVV"
M2.Laboratoire= "VVT" 
Chaque instance à sa propre variable Laboratoire (Non Shared)


Par contre:

M1.Societe="ooo"
entraîne que M2.societe est aussi égal à "ooo"

La propriété Societe de toutes les instances de Medicament a la même valeur

Medicament.Societe est aussi égal à "ooo" Ici on a directement utilisé le nom de la classe.

(Ne pas confondre avec une variable Static qui est une variable qui conserve sa valeur, mais qui a une valeur pour chaque instance).


Une variable, comme tous les membres d'une classe peut être, Private, Public, mais aussi Protected (accessible par les seules méthodes de la classe ou des objets dérivés)

warning Il faut en général déclarer les variables interne en 'Private': elles sont internes et non accessible à l'extérieur de la Classe.

XV-B-1-d. Ajouter des propriétés grâce à 'Property'

Les propriétés permettent d'associer des données à une Classe.

On rappelle qu'une Property peut être utilisée comme cela:

Dim MonMedicament As New Medicament()
MonMedicament.Nom= "Amoxicilline" : Nom est une Property.
Vu de l'extérieur cela pourrait ressembler à une variable, en fait dans l'implémentation c'est complètement différent. Il y a du code permettant d'écrire ou de lire la property.

Pour créer une Property:

Tapez 'Property Nom' puis validez, la définition de la propriété est générée en faisant apparaître

  • un bloc Get qui correspond à la lecture de la propriété par l'utilisateur.
  • un bloc Set qui correspond à l'écriture de la propriété par l'utilisateur, on récupère la valeur dans le paramètre value.

Property Nom() 
Get  
End Get
Set (By Val Value)
End Set
End Property
J'ajoute Public pour que cette propriété soit accessible hors de la classe, j'indique que c'est une String. Lors de la lecture de la propriété (par l'utilisateur de l'instance) Get retourne (grâce à Return) la valeur _mNom qui est une variable privée de la classe et qui sert à stocker la valeur de la propriété. Lors de l'écriture de la variable, Set récupère la valeur dans Value et la met dans _mNom:

Public Class Medicament
 
'Variable privée (Attribut) servant à stocké en interne le nom.
Private _mNom As String
 
'Propriété Nom
Public Property Nom() as String
Get  
    Return _mNom
End Get
Set(By Val Value)
    _mNom=value
End Set
End Property
 
End Class
Encapsulation:
La variable '-mNom' est encapsulée: l'utilisateur qui utilise une instance de la classe, ne voit pas ce qui se passe (ici c'est très simple) quand il utilise le nom, il ne voit pas l'implémentation (l'implémentation c'est Get...Set...), il ne voit que l'interface c'est à dire .Nom ; Il n'a pas accès à _mNom.


Si l'utilisateur tape: MonMedicament.Nom=" Aspirine" , c'est le code Set..EndSet qui est exécuté.

Si l'utilisateur tape: Dim s As String= MonMedicament.Nom , c'est le code Get..EndGet qui est exécuté.


Une propriété peut être en lecture seule:

Public ReadOnly Property InitialeNom() As String
Get
 Return Left(_mNom,1) 
End Get
End Property
Mais aussi en écriture seule grâce à WriteOnly.


Les propriétés comme les méthodes peuvent être Public, Private, Protected, Friend, ProtectedFrient:


A partir de VB 2005, on peut créer des Property avec une portée différente pour le Set et le Get:

Public Class employee
    Private salaryValue As Double
    Protected Property salary() As Double
        Get
            Return salaryValue
        End Get
        Private Set(ByVal value As Double)
            salaryValue = value
        End Set
    End Property
End Class

Implémentation automatique. A partir de vb 2010 une propriété peut être écrite (implémentée) de manière simple et rapide: plus besoin de Get et Set:

'Code complet
Private _MaProperty As String = "Empty"
Property MaProperty As String
    Get
        Return _MaProperty
    End Get
    Set(ByVal value As String)
        _MaProperty = value
    End Set
End Property

'Peut être remplacé par:
Property MaProperty As String = "Empty"
La dernière ligne génère '_MaProperty' qui est un champ privé.


On peut même indiquer une valeur par défaut ou un type:

Property ID() As Integer = -2
Property ManList() As New List(Of Man)

Petit exemple: Créons une classe 'Personne' avec 2 propriétés: 'Nom' et 'Prenom'.
On instancie un objet 'FirstPersonne' de type 'Personne' et on donne une valeur aux 2 propriétés de l'objet.

Public Class Personne
    Property Nom As String
    Property Prenom As String
End Class
.....


Dim FirstPersonne As New Personne
FirstPersonne.Nom= "Las"
FirstPersonne.Prenom= "Philippe"

'En VB 2010 on peut aussi écrire:
Dim FirstPersonne As New Personne With {.Nom = "Las", .Prenom = "Philippe"}


XV-B-1-e. Méthode

Une Classe peut contenir un comportement sous forme de procédures et fonctions contenant du code.

On peut ajouter une méthode à une Classe:

Les méthodes d'une classe sont les procédures Sub ou Function déclarées dans la classe.
Elles sont habituellement 'Public'.

Une méthode peut contenir du code effectuant un traitement:

Public Sub Dessine() As Double
' Code
End Sub

Une méthode peut aussi être utilisée pour lire ou écrire des variables privées, on parle dans ce cas d'accesseurs:
 
Public Class Medicament
'Variables ou Attributs
Private _nom As String
 
'Accesseurs
Public Sub GetNom() As String
    Return _nom
End Sub
 
'modificateurs
Public Sub SetNom (ByVal N As String)
    Me._nom= N
EndSub
End Class
 
SetNom est une mutateur.


XV-B-1-f. Récapitulatif Property, méthodes

  1. Un objet peut être vu comme un regroupement de données (variables et propriétés).
    La différence entre une variable et une Propriété (Property) est qu'alors que la variable est une simple variable, la Property est contrôlée par du code interne qui peut modifier le comportement de la lecture ou de l'écriture de la Property.


  2. Mais un objet va plus loin: il peut contenir un comportement sous forme de procédures et fonctions contenant du code. (Ce sont les méthodes de l'objet). Elles représentent le comportement commun de tous les objets appartenant à la classe.


Tous les éléments de la Classe peuvent être Public (visibles par l'utilisateur de la classe) ou Private (non accessibles à l'utilisateur de la classe et utilisés en interne dans la classe)

info On voit aussi qu'il faut que les variables soient 'Private' et les méthodes et Property 'Public'.

XV-B-1-g. Constructeur

Un constructeur est une procédure exécutée lors de l'instanciation.

Dans le module de classe, elle est définie par:

Sub New()
End sub
On peut ajouter des paramètres qui serviront à instancier.

Par exemple pour instancier et donner le nom en même temps:

Sub New(ByVal LeNom As String)
    _mNom=LeNom
End sub
Cela permet Dim M As New Medicament("Aspirine")

On peut définir plusieurs constructeurs avec un nombre de paramètres différents (plusieurs signatures), dans ce cas il y a surcharge, le constructeur par défaut étant celui sans paramètres.


Une autre manière de faire est d'utiliser une méthode Initialise:

Créons une classe avec une méthode Initialise.

Classe Homme
Private _Nom As String
Private _Prenom As String
Public Sub initialise(ByVal N As String, ByVal P As String)
    Me._nom = N
    Me._prenom = P
End Sub
End Class

_nom, _prenom étant des données privées de la classe Homme, les instructions :

dim p as New Homme()
p._prenom="Philippe" est refusée
On écrira donc :
dim p as New Homme
p.initialise("Monnom", "Philippe")

XV-B-1-h. Destructeur

Un objet est détruit:
  • en lui affectant la valeur Nothing.

  • si on sort de sa portée.
Une procédure Finalize (appartenant à la Classe Objet) est automatiquement appelée quand l'objet est détruit.

On peut ajouter une procédure Finalize à notre classe, qui redéfini la procédure Finalise de la Classe 'Objet'.

Protected Overrides Sub Finalize ()
End Sub

On peut y mettre le code libérant les ressources ou d'autres choses.

Noter que la procédure Finalize est ici la redéfinition (d'ou 'Overrides') de la procédure Finalize (qui est Overridable) de la Classe Objet.

Attention la méthode Finalize est exécutée quand l'objet est réellement détruit (Objet=Nothing le rend inutilisable mais il est toujours présent en mémoire). C'est parfois très tardivement que l'objet est détruit: quand il y a besoin de mémoire (c'est le Garbage Collector qui entre en action) ou à la sortie du programme.


Pour forcer la destruction on peut utiliser l'interface IDisposable:

Il faut mettre dans l'entête de la classe

Implements IDisposable

et mettre dans le code de la classe
 
Public Sub Dispose() Implements System.IDisposable.Dispose
' Code libérant les ressources (Base de données, connexion, Objets systèmes..)...
End sub

C'est une méthode Public, on peut l'appeler de l'application cliente:

M.Dispose()
M=Nothing
 
Là aussi attention, Dispose doit être appelé de manière explicite (il faut le faire, ce n'est pas automatique); quand on fait M.dispose, la procédure Dispose et le code qu'il contient sont exécutés immédiatement, par contre c'est toujours le Garbage Collector qui décide quand Finalise sera exécuté.


Dans la pratique quelle est d'utilité de gérer la destruction autrement que par Objet=Nothing si le Garbage Collector nettoie la mémoire? C'est une question.

Réponse donnée par Microsoft:

Votre composant a besoin d'une méthode Dispose s'il alloue des objets système, des connexions à la base de données et d'autres ressources rares qui doivent être libérées dès qu'un utilisateur a fini de se servir d'un composant.

Vous devez également implémenter une méthode Dispose si votre composant contient des références à d'autres objets possédant des méthodes Dispose.


XV-B-1-i. Surcharge

On peut surcharger un constructeur.
Pour cela il suffit de rajouter autant de procédure New que l'on veut avec pour chacune un nombre de paramètre différent (signatures différentes).

Exemple: On peut surcharger un constructeur:

Class Figure
Sub New()
    Bla Bla
End Sub
 
Sub New( ByVal X As Integer, ByVal Y As Integer)
     Blabla
End Sub. 
End Class
 On peut donc instancier la classe correspondante de 2 manières:
Dim A As New Figure    'Constructeur par défaut
ou
Dim A As New Figure(100,150)
 
On peut surcharger une property.
Pour cela il suffit de rajouter des procédure Property ayant le même nom de méthode avec pour chacune un nombre de paramètre différent (signature différente)

On peut ajouter Overloads mais c'est facultatif.

Exemple surchargeons un membre:

Class Figure
Public Overloads Property Calcul()
    Bla Bla
End Sub
 
Public Overloads Property Calcul( ByVal X As Integer, ByVal Y As Integer)
     Blabla
End Sub. 
End Class

XV-B-1-j. Évènement

On peut définir un évènement pour la classe.

Dans la classe:
  • Il faut déclarer l'évènement, avec le mot Event
  • Il faut utilisez l'instruction RaiseEvent pour le déclencher lorsqu'un état ou une condition le nécessite.
Exemple:

je crée une classe nommé 'Class1' qui contient un membre 'Texte'( Property Texte), si 'Texte' change, alors on déclenche l'évènement TextChange:


Public Class Class1
Private _mTexte As String
 
' Déclare un évènement
Public Event TextChange(ByVal UserName As String)
 
Public Property Texte()
Get
    Return _mTexte
End Get
Set(ByVal Value)
If Value <> _mTexte Then
  RaiseEvent TextChange("hello")'<= déclenchement de l'évènement par RaiseEvent
End If
_mTexte = Value
End Set
End Property
 
End Class

Si l'application cliente modifie la propriété .Texte d'un objet Class1 alors on compare l'ancien et le nouveau texte, s'il est différent on déclenche un évènement TextChange.


Dans l'application cliente:
  • Il faut définir dans la partie déclaration l'objet M de classe Class1 en indiquant qu'il gère des évènements.
    
    Private WithEvents  M As Class1
    

  • Dans Form_Load par exemple il faut instancier l'objet:
    
    M= New Class1()
    

  • Il faut écrire la procédure évènement avec son code:
    
    Private Sub M_TexteChange(ByVal v As String) Handles M.TextChange
        MsgBox("le texte a changé")
    End Sub
    

Ici on demande simplement quand le texte change, d'ouvrir une MessageBox.


Lors de l'utilisation:

M.Text="Nouveau text" 'déclenche la Sub M.TextChange qui dans notre exemple simple ouvre une MessageBox indiquant que le texte à changer.


On remarque que la Classe définit l'évènement, la procédure correspondant à l'évènement est dans l'application cliente.(De la même manière que quand on clique sur un objet bouton cela déclenche la procédure Bouton-Click.)


XV-B-1-k. Exception

Il est parfois utile de déclencher une exception: si l'utilisateur de la classe donne par exemple une valeur invalide à une property, une exception se déclenche indiquant que la donnée est invalide.

Dans l'exemple suivant si l'utilisateur affecte à la propriété Mavaleur une valeur négative, une exception est déclenché (Maclasse.Mavaleur=-2)

Public Property MaValeur() As Integer
    Get
    ..
    End Get
    Set (ByVal Value As Integer)
        If Value>=0 Then
            _mValeur= Value
        Else
            Throw New Exception ("La valeur " & Value.ToString & " est invalide")
        End If
    End Set
End Property

XV-B-1-l. Les Classes partielles

Les classes 'Partielles' sont possible en VB2005 (Framework 2).

Les types partiels permettent la définition d'une classe unique dans plusieurs fichiers source. La définition a une déclaration normale dans un fichier :

Public Class MaClasse
    'implementation...
End Class

Dans d'autres fichiers source, utilisez le mot-clé Partial pour indiquer au compilateur que ce code est la suite de la définition de classe d'origine :

Partial Public Class MaClasse
    'implementation...
End Class

XV-B-1-m. Méthode partielles

A partir de VB 2008. Elle sont présentes dans des Classes Partielles. Et sur des méthodes privées. Voici la syntaxe.

Partial Private Sub MyMethode()
End Sub
Exemple:

Voici la Classe:

Partial Class Product 
Private _Quantity As Integer 
Property Quantity() As Integer 
...
End Property
 
Partial Private Sub QuantityChanged() 
End Sub 
 
End Class
Ici dans la Classe initiale la méthode partielle QuantityChanged() sert à donner la signature.

L'autre Classe partielle, qui est dessous, ajoute des fonctionnalités à la méthode partielle.

Partial Class Product</b>				

Private Sub QuantityChanged()

     MsgBox("Quantity was changed to " & Me.Quantity) 

End Sub 

End Class

 

XV-B-2. Classe suite et astuces

warning Pour la suite de ce chapitre, nous sommes toujours DANS la Classe de l'objet ( et non dans l'application utilisatrice).
DANS la boite.

XV-B-2-a. Me, My, MyClass, MyBase

Dans une classe, on peut utiliser Me, My, MyClass, MyBase pour appeler une methode.

Résumons:

Me c'est l'instance en cours.

Me.Calcul dans une classe, appelle la Sub Calcul qui est dans la Classe.


MyClasse c'est l'instance en cours. Mais à la différence de Me, c'est la méthode de la classe de base (Parente) qui est appelée si cette méthode a été substituée.

MyBase c'est la classe parente.

MyBase est couramment utilisé pour accéder aux membres de la classe de base qui sont substitués ou occultés dans une classe dérivée. MyBase.New permet d'appeler explicitement un constructeur de classe de base (parente) d'un constructeur de classe dérivé.


Voyons un exemple:

On a une classe de base, une classe dérivée et on voit, quand on utilise une méthode de la classe dérivée, ce que retourne Me, MyClass et MyBase.

Class baseClass
    'Classe de base (parente)
    Public Overridable Sub testMethod()
        MsgBox("Base class string (parente)")
    End Sub
    Public Sub useMe()
        ' Utilise la classe en cours même si 
        ' la méthode a été overridé.
        Me.testMethod()
    End Sub
    Public Sub useMyClass()
        ' Utilise la classe en cours si elle a été overidé 
        ' Utilise la classe parent si  pas d' override.
        MyClass.testMethod()
    End Sub

    Public Sub useMyBase()
        ' Utilise la méthode de la classe parente.
        MyBase.testMethod()
    End Sub
End Class

Class derivedClass : Inherits baseClass
    'Classe dérivée debaseClass
    Public Overrides Sub testMethod()
        MsgBox("Derived class string (enfant)")
    End Sub
End Class

Class testClasses
    'Classe pour tester
    Sub startHere()
        Dim testObj As derivedClass = New derivedClass()
        ' Usage de Me
        ' Ce qui suit affiche  "Derived class string (enfant)" toujours.
        testObj.useMe()
        
        ' Usage de MyClasse
        ' Ce qui suit affiche  "Base class string(parente)" car testMethod overidé.
        testObj.useMyClass()
        
        ' Usage de MyBase
        ' Ce qui suit affiche  "Base class string(parente)" toujours .
        testObj.useMyBase()
    End Sub
End Class

My c'est completement différent, c'est un moyen rapide d'avoir accès à des classes de l'application, de l'ordinateur, des ressources...

Utiliser une icone nommée MyIcon qui est dans les ressources et en faire l'icone du formulaire en cours.

Me.Icon = My.Resources.MyIcon
Jouer un son qui est dans les ressources.

My.Computer.Audio.Play(My.Resources.Form1Greeting, AudioPlayMode.Background)


XV-B-2-b. Propriété par défaut

Default sert à indiquer que la propriété est la propriété par défaut.

Créons une property par défaut:

Class MyClasse
Default Property MonItem As String
..
End Property
End Class
 

Maintenant, il n'est plus nécessaire d'utiliser le nom de la propriété quand on y accède.

Dim MyCollection As New MyClasse
On peut écrire:

MyCollection.MonItem (index)
Ou

MyCollection(index)    'MonItem est omis

Bien sur, il ne peut y avoir qu'une seule property par défaut.


XV-B-2-c. Méthode de Classe avec Shared

Vous pouvez ajouter à votre membre : Shared. Cela signifie que la variable, la propriété ou la méthode déclarée comme Shared est partagée par toutes les instances de la classe: c'est une méthode de classe.


Une méthode déclarée dans une classe sans modificateur Shared est appelée méthode d'instance. Une méthode d'instance opère sur une instance donnée.

Pour une variable non Shared, dans chaque instance la variable a sa valeur propre.

Une variable Shared est commune à toutes les instances de la Class et même à la Classe elle-même sans avoir besoin de l'instancier. C'est une variable de Classe.

L'exemple suivant illustre les règles d'accès aux membres d'instance et Shared :


Class Test
   Private _x As Integer
   Private Shared _y As Integer
   
   Sub F()
      _x = 1 ' Ok, c'est équivalent à Me._x = 1.
      _y = 1 ' Ok, c'est équivalent à Test._y = 1.
   End Sub
   
   Shared Sub G()
      _x = 1 ' Erreur, on ne peut accéder à Me._x.
      _y = 1 ' Ok, c'est équivalant à Test._y = 1.
   End Sub
End Class
   
   Shared Sub Main()
      Dim t As New Test()
      t._x = 1 ' Ok.
      t._y = 1 ' Ok.
      Test._x = 1 ' Erreur, on accède à x seulement par une instance.
      Test._y = 1 ' Ok  on peut accéder à y avec le nom de la classe car y est shared.
   End Sub
La méthode F montre que, dans une fonction d'instance membre, un identificateur peut être utilisé pour accéder à des membres d'instance et à des membres Shared. La méthode G montre que, dans une fonction membre Shared, il est erroné d'accéder à une instance membre via un identificateur. En d'autres termes dans une méthode Shared on n'a accès qu'au variable Shared. Quant à la méthode Main, elle montre que, dans une expression d'accès au membre, l'accès aux membres d'instance s'effectue par l'intermédiaire des instances, alors que l'accès aux membres Shared est possible via des types ou des instances.


XV-B-2-d. Création d'un compteur d'instances

Je veux savoir combien il a été crée d'instance de 'Médicament':

Class MyClasse
'Créons une variable commune à toutes les instances

Private Shared Nb as Integer=0
'Le constructeur va l'incrémenter à chaque instanciation:

Sub New()
    Nb+=1
End sub
 

'Il suffit de lire sa valeur pour savoir le nombre d'objet Medicament:

Public ReadOnly Property NbInstance()
    Get
        NbInstance=Nb
    End Get
End Property 
 
End Class
 

XV-B-2-e. Création d'un identifiant unique d'instance

Pour chaque instance, je veux avoir un identifiant unique, un globally unique identifier (GUID).

Private m_ID As System.Guid
Sub New()
    m_ID = System.Guid.NewGuid
End Sub
Exemple d'identifiant unique:

'0f8fad5b-d9cb-469f-a165-70867728950e  
Chaque instance ayant un identifiant unique, je peux ainsi 'repérer' les instances (en créant une property ReadOnly afin de lire cet identifiant)

Il existe une très faible probabilité pour que le nouveau GUID soit égal à zéro ou égal à un autre GUID


XV-B-2-f. Singleton

Parfois , on a une classe avec laquelle on veut créer une instance et une seule.

Private Sub New()
New doit-être toujours private pour empêcher d'instancier avec New

Un singleton est construit grâce à une méthodes de classe nommé 'GetInstance' (sans avoir à instancier).


Shared Function getInstance() As sing
Cette fonction qui s'appelle toujours getInstance va servir à instancier une fois la variable Instance.


Shared instance As sing
Cette variable est la base du Singleton. Elle s'appelle Instance (par convention) elle est du même type que la class et contient l'instance unique.


Public Class sing
'Déclaration de l'instance Singleton
Shared instance As sing
 
Private Sub New()'Pas oublier de mettre Private 
    MyBase.New()
End Sub
Shared Function getInstance() As sing 'Voici la méthode de classe
 
If IsNothing(instance) Then 'Si le singleton n'est pas créé, alors faut le créé
    instance = New sing
End If
Return instance
End Function
...
...
End Class

Comment utiliser cette Classe?

Dim t As sing =  sing.getInstance
Remarque:

  • Si on fait ensuite Dim t1 As sing = sing.getInstance c'est la même instance qui est retournée. On ne peut en créer qu'une..
  • Si on écrit Dim t As New sing :cela plante.

On peut ajouter une protection contre les multi thread trop rapide avec SyncLock GetType(sing)


    Shared Function getInstance() As sing
         
        If IsNothing(instance) Then 
            SyncLock GetType(sing) 
                 If IsNothing(instance) Then 
                    instance = New sing 
                end if 
            End SyncLock 
        End If 
        Return instance 
    End Function 

XV-B-2-g. Surcharge d'opérateur

A partir de VB 2005, on peut surcharger les opérateurs + - * / mais aussi _ ^ & Like And Or Xor Not < > = << >> CType IsTrue, IsFalse.

Cela signifie que pour cette classe l'opérateur aura le comportement que vous lui donnerez.

Exemple: surchargeons l'opérateur +

Public Classe height
    ...
    Public Shared Operator +(ByVal h1 As height, ByVal h2 As height)As height
        Return New height(h1.feet + h2.feet, h1.inches + h2.inches)
    End Operator
End Structure
La routine doit être Shared, de plus si on surcharge certains opérateurs, il faut aussi surcharger leur inverse: si on surcharge '>' , il faut surcharger '<'.


Surcharge de IsTrue, IsFalse CType

Si on teste un boolean, il a la valeur True ou False.

Si par contre je crée une classe nommée 'Personne', je peux définir comment une instance sera considérée comme égale à True. Il faut surcharger l'opérateur IsTrue en lui indiquant dans quelle condition l'instance sera considérée comme =True:

Exemple:

J'ai une instance e de type Personne, si e.Present =True, dans ce cas je veux que e soit considéré comme True; il faut écrire dans la Classe 'personne':

Public Shared Operator IsTrue(ByVal e As Personne) As Boolean

If e Is Nothing Then

    Return False

Else

    Return e.Present

End If

End Operator
Pour définir l'opérateur IsFalse, c'est simple: c'est Not e

Public Shared Operator IsFalse(ByVal e As Personne) As Boolean

    Return Not e

End Operator
Ensuite je pourrais utiliser des instructions de la forme:

If e then.. 

Surcharge de CType:

Je peux définir dans une classe comment CType va fonctionner:

Pour cela dans la classe Personne, je vais définir les 3 possibilités:

Public Shared Widening Operator CType(ByVal e As Personne) As String

Return e.Nom + " " + e.Prenom

End Operator

 

Public Shared Widening Operator CType(ByVal  e As Personne) As Date

If e Is Nothing Then

    Return Nothing

Else

    Return e.DateDeNaissance

End If

End Operator

 

Public Shared Widening Operator CType(ByVal  e As Personne) As Boolean

    If e Is Nothing Then Return False Else Return e.Present

End Operator
Ainsi

CType(UnePersonne,String) retourne Nom Prenon

CType(UnePersonne,Date) retourne la date de naissance

CType(UnePersonne,Boolean) retourne True ou False.



XV-B-2-h. Surcharge de ToString

On va créer une classe 'temperature' et on va surcharger ToString pour créer un format propre à 'temperature'.

Public Class Temperature
    Private temp As Decimal

    Public Sub New(ByVal temperature As Decimal)
        Me.temp = temperature
    End Sub

    Public Overrides Function ToString() As String
        Return Me.temp.ToString("N3") + "°C"  'format nombre avec 3 chiffres après la virgule = '°C'
    End Function
End Class
Pour utiliser::

        Dim currentTemperature As New Temperature(23.6D)
        Console.WriteLine("The current temperature is {0}.", currentTemperature)
        'Affiche The current temperature is 23,600°C.


XV-C. Créer un composant (Bibliothèque de Classe et de Contrôles)

On a vu qu'on pouvait CREER SES PROPRES CLASSES dans un projet, mais on peut aussi:
  • créer une Classe autonome qui sera utilisée par plusieurs autres programmes, c'est une Bibliothèque de Classe.
  • créer un contrôle utilisateur utilisé lui aussi par d'autres programmes.
Maintenant nous allons créer des classes ou contrôles, ils seront utilisés par une application cliente.


XV-C-1. Créer une Bibliothèque de classes

Pour créer une bibliothèque de Classe, il faut faire menu 'Fichier', 'Nouveau', 'Projet':

Cliquer sur l'icône 'Bibliothèque de Classes'.

Le nom par défaut est ClassLibrary1 , valider sur Ok.

Dans la fenêtre principale, il y a:

Public Class Class1
End Class
On peut écrire le code, la description d'une classe avec ses propriétés, ses méthodes, ses constructeurs...(Voir page précédente)

On peut ajouter une autre Classe (Menu Projet, ajouter une Classe), ou importer une Classe (Menu Projet, Ajouter un élément existant)

info Il n'y a pas de procédure Sub Main. (c'est évident, un composant n'est jamais autonome; c'est l'application cliente qui a cette procédure).
Une bibliothèque de classe ne possède pas les composants que possède une application Windows, il n'y a pas d'interface utilisateur, pas de MessageBox, pas de gestion du curseur; c'est l'application cliente qui s'occupe de gérer l'interface.

XV-C-1-a. Namespace

Permet de créer un espace de nom dans le composant:

NameSpace Outils
End
 

Il peut y avoir plusieurs niveau:

NameSpace Outils
NameSpace Marteau
....
End
End
 

Equivalent à:

NameSpace Outils
Classe Marteau
....
End Class
End

Dans l'application il faudra après avoir référencé le composant (la Dll) importer l'espace de nom pour utiliser le composant.

Imports Outils.Marteau
 

XV-C-1-b. Utilisation du composant

Il faut enfin enregistrer la bibliothèque, la compiler.

Comment utiliser ce composant?
  • Si la bibliothèque de Classe a été compilée, on obtient une DLL:

    Il faut la référencer: Ajouter la Dll au projet (Menu Projet, Ajouter une référence)

    Importer l'espace de nom par Imports Espace de nom au début du module.

    On peut ensuite utiliser la Classe dans l'application cliente.

  • On peut travailler en même temps sur l'application cliente et le projet de la bibliothèque de Classe en les chargeant tous les 2 dans une solution.

XV-C-2. Créer un 'contrôle utilisateur' à partir d'un contrôle existant en le modifiant

Permet de créer un contrôle spécifique qui enrichira la 'Boite à outils' :

(Pour les 'anciens' c'est comme un contrôle OCX, sauf que c'est un contrôle .NET et que c'est un fichier .dll)

Exemple: Créer un bouton avec un aspect spécifique à partir du bouton habituel (Ajout d'un cadre).

  1. Il faut créer une bibliothèque de contrôle:
    Pour créer une bibliothèque de Contrôle, il faut faire menu Fichier, Nouveau, Projet, Icône 'Bibliothèque de contrôle Windows' : Nom du projet: WindowControle par exemple.

    On obtient une fenêtre qui ressemble à un formulaire mais sans bord,on peut y ajouter un contrôle (un bouton par exemple )

    Si on regarde le code correspondant, Vb a crée une Classe UserControl1 qui hérite de la classe Forms.UserControl
    
    Public Class UserControl1
    Inherits System.Windows.Forms.UserControl
    End Class
    
    Il suffit de substituer à UserControl le nom du contrôle que vous voulez utiliser comme base pour hériter de tous ses éléments. On remplace donc par:
    
    Public Class MonBouton
    Inherits System.Windows.Forms.Button
    End Class
    
    Le 'Design' devient:

  2. Il faut modifier l'aspect graphique du bouton:
    Pour cela si vous voulez modifier l'apparence du contrôle, il faut remplacer la méthode OnPaint de Button par la votre(celle-ci dessine le contrôle). Au sein de cette méthode, vous devez appeler la méthode OnPaint de la base (de la classe mère), puis ajouter vos propres fonctions de dessin.

    Il faut donc ajouter la procédure:
    
    Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
    MyBase.OnPaint(e) 'Appel à la méthode de la classe de base, ce qui dessine le bouton
    Dim myPen As New Pen(Color.Purple, 3)
    e.Graphics.DrawRectangle(myPen, 3, 3, Me.Width - 6, Me.Height - 6) 'Ajoute un cadre sur le dessin du bouton
    End Sub
    
    On rappelle que l'argument e est le graphique du bouton.

  3. Compilation:
    Quand le composant est terminé il faut créer la Dll:

    Menu 'Générer' puis 'Générer WindowControle'

    On obtient WindowControle.Dll dans le répertoire /bin sous les sources.

  4. Utilisation du composant dans une autre application VB.
    Dans un autre projet VB, si je veux utiliser mon composant MonBouton, il faut l'ajouter dans la boite à outils:

    Pour cela cliquer avec le bouton droit de la souris dans la boite à outils. Un menu contextuel s'ouvre, cliquer sur 'Ajouter/Supprimer des éléments' puis dans la fenêtre qui s'ouvre cliquez sur 'parcourir'.. cliquez sur WindowControle.Dll , le composant MonBouton apparaît dans la Boite à outils.


    Il suffit de le saisir et de le déplacer dans un des formulaires comme un bouton normal.


    Toutes les procédures évènements (Comme MonBouton1_Click) sont disponibles; elles ont été héritées de Button.

Ce qu'il faut comprendre:

C'est que votre nouveau bouton hérite de Control, une classe qui possède un grand nombre d'événements et de méthodes qui n'apparaissent pas dans les listes déroulantes, car inutile dans l'utilisation de l'objet mais très utile dans le comportement d'un objet. C'est le cas de OnPaint OnKeyDown et OnMouseDown... qui déclenchent les évènements Paint, KeyDown, MouseDown. On redéfini ces méthodes (avec Overrides), dans la méthode redéfini on appelle quand même la méthode de la classe mère puis on ajoute les modifications de fonctionnalités .

Exemple:

Différencier une zone droite et une zone gauche sur le bouton:

On utilise l'évènement OnMouseDown, il a pour paramètre e qui contient les coordonnées de la souris (e.x et e.y)

Protected Overrides Sub OnMouseDown(ByVal e As MouseEventArgs)
 
MyBase.OnMouseDown(e) 'Appel à la méthode de la classe de base
If e.X < Me.Width / 2 Then 
    MessageBox.Show("Click sur partie gauche") 
Else
    MessageBox.Show("Click sur partie droite") 
End if
End Sub
 
MessageBox peut être remplacé par un raisevent pour déclencher un évènement.

info On vient de créer un composant héritant d'un contrôle, puis on en a modifié les fonctionnalités.

XV-C-3. Créer un 'contrôle utilisateur' contenant un ou plusieurs contrôles pilotés

Pour créer une bibliothèque de Contrôle (un contrôle utilisateur), il faut faire menu Fichier, Nouveau, Projet, Icône 'Bibliothèque de contrôle Windows' : Nom du projet: WindowControle par exemple.

On obtient une fenêtre qui ressemble à un formulaire mais sans bord,on peut y ajouter un contrôle (un textBox par exemple comme ici) ou plusieurs contrôles.

warning Ici la zone de fond grise est importante, le contrôle crée correspond à la totalité de la zone grise du formulaire sans bord, ce qui n'est pas pratique quand on utilise le contrôle (j'en ai dessiné un petit, et je ne voyais pas la textebox!!) Il est donc conseillé de réduire la surface.
Si on regarde le code correspondant, Vb a crée une Classe UserControl1 qui hérite de la classe Forms.UserControl

Public Class UserControl1
Inherits System.Windows.Forms.UserControl
End Class
 

Dans ce Usercontrol il y a les procédures privées des évènements des composants,

Private Button1_Click
End Sub
Bien sur, elles ne seront pas visibles ni accessibles par l'utilisateur du composant.


L'interface du Usercontrol (ce que verra l'utilisateur du composant) est créer de toute pièce comme dans un module de Class. Si on double-clique sur le fond, on voit quand même apparaître:

Private Sub UserControl1_Load(..
End Sub
Mais il faut rajouter des membres publiques qui seront accessibles à l'utilisateur du composant. On utilise pour cela les 'Property', 'Sub' et 'variables' publiques pour créer une interface. Le code contenu dans ces procédures de l'interface va 'piloter' le ou les contrôles (comme le TextBox1). Ce code modifie (dans notre exemple) le comportement du TextBox initial.

Ici je vais créer une propriété LeTexte qui est le texte qui sera affiché dans le TextBox1. Cette propriété LeTexte va 'piloter' TextBox1.text. Je modifie le comportement de TextBox1.text en empêchant d'afficher Toto (c'est idiot!! ).

Public Property LeTexte() As String
    Get
        LeTexte=TextBox1.Text
    End Get
    Set (ByVal Value As String)
        If Value <> "toto" Then
            TextBox1.Text= Value
        End if
    End Set
End Property

Je génère la solution, ajouter WindowControle.Dll à la boite à outils, je mets le nouveau composant sur un formulaire; il se nommera UserControl1.

Pour utiliser la propriété précédemment écrite :

UserControl1.LeTexte="lulu"    'lulu apparaît dans le textbox
 
UserControl1.LeTexte="toto"    'rien n' apparaît dans le textbox: : j'ai bien modifié le comportement du textbox 
'et c'est transparent pour l'utilisateur.
 
info On vient de créer un composant avec la Classe UserControl (au lieu de Forms dans un formulaire ), on a écrit son interface.
Remarque: si on veut avoir accès à une sub événement du contrôle qui est dans un composant, il faut que dans le composant la Sub évènement soit Public.


Autre exemple:

Voir cet autre remarquable exemple de création d'un composant (par CGi et neo51 sur developpez.com): Composant horloge: code source, explication claire: un régal.

 

Les sources présentés sur cette page sont libres de droits, et vous pouvez les utiliser à votre convenance. Par contre cette page de présentation de ces sources constitue une oeuvre intellectuelle protégée par les droits d'auteurs. Copyright © . Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages et intérêts. Cette page est déposée à la SACD.

Vos questions techniques : forum d'entraide Accueil - Publiez vos articles, tutoriels, cours et rejoignez-nous dans l'équipe de rédaction du club d'entraide des développeurs francophones. Nous contacter - Copyright 2000..2005 www.developpez.com